Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 10 pull requests #107161

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
799fa60
llvm-wrapper: adapt for LLVM API change
krasimirgg Dec 24, 2022
13e25b8
Improve the documentation of `black_box`
tgross35 Dec 25, 2022
fe96c11
fix #104440
TaKO8Ki Jan 16, 2023
f6d8abf
Re-enable building rust-analyzer on riscv64
cuviper Jan 18, 2023
fa7d17d
Create new bootstrap team
albertlarsan68 Jan 19, 2023
d3cfe97
Custom MIR: Support binary and unary operations
tmiasko Jan 19, 2023
ec3da87
Add note about absolute paths to Path::join
Erk- Jan 20, 2023
d8f8adf
add example of joining with a absolute path
Erk- Jan 20, 2023
8742fd9
Label closure captures/generator locals that make opaque types recursive
compiler-errors Jan 8, 2023
397e4b1
Migrate scraped-examples top and bottom "borders" to CSS variables
GuillaumeGomez Jan 21, 2023
372ad13
Extend rustdoc GUI test for scraped examples top and bottom "borders"
GuillaumeGomez Jan 21, 2023
2489889
Add compare-mode-next-solver
compiler-errors Jan 20, 2023
d6a411c
Implement some more predicates
compiler-errors Jan 20, 2023
444cbcd
Address goal nits
compiler-errors Jan 20, 2023
79d33b7
Rollup merge of #106113 - krasimirgg:llvm-16-ext-tyid, r=nikic
matthiaskrgr Jan 21, 2023
66aa7d8
Rollup merge of #106144 - tgross35:patch-1, r=Mark-Simulacrum
matthiaskrgr Jan 21, 2023
b41d8d8
Rollup merge of #106578 - compiler-errors:recursive-opaque-closure, r…
matthiaskrgr Jan 21, 2023
0facfcb
Rollup merge of #106935 - TaKO8Ki:fix-104440, r=cjgillot
matthiaskrgr Jan 21, 2023
cb2f0fb
Rollup merge of #107015 - cuviper:ra-riscv64, r=Mark-Simulacrum
matthiaskrgr Jan 21, 2023
24bcb15
Rollup merge of #107029 - albertlarsan68:patch-2, r=Mark-Simulacrum
matthiaskrgr Jan 21, 2023
fba722a
Rollup merge of #107085 - tmiasko:custom-mir-operators, r=oli-obk
matthiaskrgr Jan 21, 2023
0f0bfed
Rollup merge of #107102 - compiler-errors:new-solver-new-candidats-4,…
matthiaskrgr Jan 21, 2023
9f0f792
Rollup merge of #107114 - Erk-:add-absolute-note-to-path-join, r=m-ou-se
matthiaskrgr Jan 21, 2023
6a040d7
Rollup merge of #107152 - GuillaumeGomez:migrate-to-css-var, r=notriddle
matthiaskrgr Jan 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 53 additions & 6 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1391,11 +1391,15 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed
///
/// If all the return expressions evaluate to `!`, then we explain that the error will go away
/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> ErrorGuaranteed {
fn opaque_type_cycle_error(
tcx: TyCtxt<'_>,
opaque_def_id: LocalDefId,
span: Span,
) -> ErrorGuaranteed {
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");

let mut label = false;
if let Some((def_id, visitor)) = get_owner_return_paths(tcx, def_id) {
if let Some((def_id, visitor)) = get_owner_return_paths(tcx, opaque_def_id) {
let typeck_results = tcx.typeck(def_id);
if visitor
.returns
Expand Down Expand Up @@ -1431,28 +1435,71 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E
.filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
.filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
{
struct OpaqueTypeCollector(Vec<DefId>);
#[derive(Default)]
struct OpaqueTypeCollector {
opaques: Vec<DefId>,
closures: Vec<DefId>,
}
impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
self.0.push(def);
self.opaques.push(def);
ControlFlow::Continue(())
}
ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => {
self.closures.push(def_id);
t.super_visit_with(self)
}
_ => t.super_visit_with(self),
}
}
}
let mut visitor = OpaqueTypeCollector(vec![]);

let mut visitor = OpaqueTypeCollector::default();
ty.visit_with(&mut visitor);
for def_id in visitor.0 {
for def_id in visitor.opaques {
let ty_span = tcx.def_span(def_id);
if !seen.contains(&ty_span) {
err.span_label(ty_span, &format!("returning this opaque type `{ty}`"));
seen.insert(ty_span);
}
err.span_label(sp, &format!("returning here with type `{ty}`"));
}

for closure_def_id in visitor.closures {
let Some(closure_local_did) = closure_def_id.as_local() else { continue; };
let typeck_results = tcx.typeck(closure_local_did);

let mut label_match = |ty: Ty<'_>, span| {
for arg in ty.walk() {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Alias(ty::Opaque, ty::AliasTy { def_id: captured_def_id, .. }) = *ty.kind()
&& captured_def_id == opaque_def_id.to_def_id()
{
err.span_label(
span,
format!(
"{} captures itself here",
tcx.def_kind(closure_def_id).descr(closure_def_id)
),
);
}
}
};

// Label any closure upvars that capture the opaque
for capture in typeck_results.closure_min_captures_flattened(closure_local_did)
{
label_match(capture.place.ty(), capture.get_path_span(tcx));
}
// Label any generator locals that capture the opaque
for interior_ty in
typeck_results.generator_interior_types.as_ref().skip_binder()
{
label_match(interior_ty.ty, interior_ty.span);
}
}
}
}
}
Expand Down
47 changes: 26 additions & 21 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,34 +825,39 @@ pub trait LintContext: Sized {
debug!(?param_span, ?use_span, ?deletion_span);
db.span_label(param_span, "this lifetime...");
db.span_label(use_span, "...is used only here");
let msg = "elide the single-use lifetime";
let (use_span, replace_lt) = if elide {
let use_span = sess.source_map().span_extend_while(
use_span,
char::is_whitespace,
).unwrap_or(use_span);
(use_span, String::new())
} else {
(use_span, "'_".to_owned())
};
db.multipart_suggestion(
msg,
vec![(deletion_span, String::new()), (use_span, replace_lt)],
Applicability::MachineApplicable,
);
if let Some(deletion_span) = deletion_span {
let msg = "elide the single-use lifetime";
let (use_span, replace_lt) = if elide {
let use_span = sess.source_map().span_extend_while(
use_span,
char::is_whitespace,
).unwrap_or(use_span);
(use_span, String::new())
} else {
(use_span, "'_".to_owned())
};
debug!(?deletion_span, ?use_span);
db.multipart_suggestion(
msg,
vec![(deletion_span, String::new()), (use_span, replace_lt)],
Applicability::MachineApplicable,
);
}
},
BuiltinLintDiagnostics::SingleUseLifetime {
param_span: _,
use_span: None,
deletion_span,
} => {
debug!(?deletion_span);
db.span_suggestion(
deletion_span,
"elide the unused lifetime",
"",
Applicability::MachineApplicable,
);
if let Some(deletion_span) = deletion_span {
db.span_suggestion(
deletion_span,
"elide the unused lifetime",
"",
Applicability::MachineApplicable,
);
}
},
BuiltinLintDiagnostics::NamedArgumentUsedPositionally{ position_sp_to_replace, position_sp_for_msg, named_arg_sp, named_arg_name, is_formatting_arg} => {
db.span_label(named_arg_sp, "this named argument is referred to by position in formatting string");
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ pub enum BuiltinLintDiagnostics {
param_span: Span,
/// Span of the code that should be removed when eliding this lifetime.
/// This span should include leading or trailing comma.
deletion_span: Span,
deletion_span: Option<Span>,
/// Span of the single use, or None if the lifetime is never used.
/// If true, the lifetime will be fully elided.
use_span: Option<(Span, bool)>,
Expand Down
20 changes: 9 additions & 11 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1349,18 +1349,16 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
return LLVMBFloatTypeKind;
case Type::X86_AMXTyID:
return LLVMX86_AMXTypeKind;
#if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0)
case Type::DXILPointerTyID:
report_fatal_error("Rust does not support DirectX typed pointers.");
break;
#endif
#if LLVM_VERSION_GE(16, 0)
case Type::TypedPointerTyID:
report_fatal_error("Rust does not support typed pointers.");
break;
#endif
default:
{
std::string error;
llvm::raw_string_ostream stream(error);
stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID()
<< " for the type: " << *unwrap(Ty);
stream.flush();
report_fatal_error(error.c_str());
}
}
report_fatal_error("Unhandled TypeID.");
}

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::AddressOf { mutability, arg } => Ok(
Rvalue::AddressOf(*mutability, self.parse_place(*arg)?)
),
ExprKind::Binary { op, lhs, rhs } => Ok(
Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)))
),
ExprKind::Unary { op, arg } => Ok(
Rvalue::UnaryOp(*op, self.parse_operand(*arg)?)
),
_ => self.parse_operand(expr_id).map(Rvalue::Use),
)
}
Expand Down
22 changes: 19 additions & 3 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2188,15 +2188,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let deletion_span = || {
if params.len() == 1 {
// if sole lifetime, remove the entire `<>` brackets
generics_span
Some(generics_span)
} else if param_index == 0 {
// if removing within `<>` brackets, we also want to
// delete a leading or trailing comma as appropriate
param.span().to(params[param_index + 1].span().shrink_to_lo())
match (
param.span().find_ancestor_inside(generics_span),
params[param_index + 1].span().find_ancestor_inside(generics_span),
) {
(Some(param_span), Some(next_param_span)) => {
Some(param_span.to(next_param_span.shrink_to_lo()))
}
_ => None,
}
} else {
// if removing within `<>` brackets, we also want to
// delete a leading or trailing comma as appropriate
params[param_index - 1].span().shrink_to_hi().to(param.span())
match (
param.span().find_ancestor_inside(generics_span),
params[param_index - 1].span().find_ancestor_inside(generics_span),
) {
(Some(param_span), Some(prev_param_span)) => {
Some(prev_param_span.shrink_to_hi().to(param_span))
}
_ => None,
}
}
};
match use_set {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_trait_selection/src/solve/assembly.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly.

use super::infcx_ext::InferCtxtExt;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::elaborate_predicates;
Expand Down Expand Up @@ -148,9 +148,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if goal.predicate.self_ty().is_ty_var() {
return vec![Candidate {
source: CandidateSource::BuiltinImpl,
result: self
.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
.unwrap(),
result: self.make_canonical_response(Certainty::AMBIGUOUS).unwrap(),
}];
}

Expand Down
83 changes: 76 additions & 7 deletions compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@

use std::mem;

use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::Obligation;
use rustc_middle::infer::canonical::Certainty as OldCertainty;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{RegionOutlivesPredicate, ToPredicate, TypeOutlivesPredicate};
use rustc_middle::ty::{
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
};
use rustc_span::DUMMY_SP;

use crate::traits::ObligationCause;
Expand Down Expand Up @@ -87,6 +90,8 @@ pub enum Certainty {
}

impl Certainty {
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);

/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
/// use this function to unify the certainty of these goals
pub fn unify_and(self, other: Certainty) -> Certainty {
Expand Down Expand Up @@ -243,16 +248,28 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
self.compute_region_outlives_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Subtype(predicate) => {
self.compute_subtype_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Coerce(predicate) => {
self.compute_coerce_goal(Goal { param_env, predicate })
}
ty::PredicateKind::ClosureKind(def_id, substs, kind) => self
.compute_closure_kind_goal(Goal {
param_env,
predicate: (def_id, substs, kind),
}),
ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::AMBIGUOUS),
// FIXME: implement these predicates :)
ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::ConstEvaluatable(_)
| ty::PredicateKind::ConstEquate(_, _)
| ty::PredicateKind::TypeWellFormedFromEnv(_)
| ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::Yes),
| ty::PredicateKind::ConstEquate(_, _) => {
self.make_canonical_response(Certainty::Yes)
}
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
}
} else {
let kind = self.infcx.replace_bound_vars_with_placeholders(kind);
Expand All @@ -275,6 +292,58 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
) -> QueryResult<'tcx> {
self.make_canonical_response(Certainty::Yes)
}

fn compute_coerce_goal(
&mut self,
goal: Goal<'tcx, CoercePredicate<'tcx>>,
) -> QueryResult<'tcx> {
self.compute_subtype_goal(Goal {
param_env: goal.param_env,
predicate: SubtypePredicate {
a_is_expected: false,
a: goal.predicate.a,
b: goal.predicate.b,
},
})
}

fn compute_subtype_goal(
&mut self,
goal: Goal<'tcx, SubtypePredicate<'tcx>>,
) -> QueryResult<'tcx> {
if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
// FIXME: Do we want to register a subtype relation between these vars?
// That won't actually reflect in the query response, so it seems moot.
self.make_canonical_response(Certainty::AMBIGUOUS)
} else {
self.infcx.probe(|_| {
let InferOk { value: (), obligations } = self
.infcx
.at(&ObligationCause::dummy(), goal.param_env)
.sub(goal.predicate.a, goal.predicate.b)?;
self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|pred| pred.into()).collect(),
)
})
}
}

fn compute_closure_kind_goal(
&mut self,
goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>,
) -> QueryResult<'tcx> {
let (_, substs, expected_kind) = goal.predicate;
let found_kind = substs.as_closure().kind_ty().to_opt_closure_kind();

let Some(found_kind) = found_kind else {
return self.make_canonical_response(Certainty::AMBIGUOUS);
};
if found_kind.extends(expected_kind) {
self.make_canonical_response(Certainty::Yes)
} else {
Err(NoSolution)
}
}
}

impl<'tcx> EvalCtxt<'_, 'tcx> {
Expand Down
Loading