diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 1535837fd05..d1ae8c1fdbd 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -294,27 +294,6 @@ impl<'a> AstValidator<'a> { } } - fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) { - // Check only lifetime parameters are present and that the lifetime - // parameters that are present have no bounds. - let non_lt_param_spans: Vec<_> = params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if !param.bounds.is_empty() { - let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); - self.session.emit_err(ForbiddenLifetimeBound { spans }); - } - None - } - _ => Some(param.ident.span), - }) - .collect(); - if !non_lt_param_spans.is_empty() { - self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans }); - } - } - fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { self.check_decl_num_args(fn_decl); self.check_decl_cvaradic_pos(fn_decl); @@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> { ) .emit(); }); - self.check_late_bound_lifetime_defs(&bfty.generic_params); if let Extern::Implicit(_) = bfty.ext { let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo()); self.maybe_lint_missing_abi(sig_span, ty.id); @@ -1318,9 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { for predicate in &generics.where_clause.predicates { match predicate { WherePredicate::BoundPredicate(bound_pred) => { - // A type binding, eg `for<'c> Foo: Send+Clone+'c` - self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); - // This is slightly complicated. Our representation for poly-trait-refs contains a single // binder and thus we only allow a single level of quantification. However, // the syntax of Rust permits quantification in two places in where clauses, @@ -1396,11 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_param_bound(self, bound) } - fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) { - self.check_late_bound_lifetime_defs(&t.bound_generic_params); - visit::walk_poly_trait_ref(self, t); - } - fn visit_variant_data(&mut self, s: &'a VariantData) { self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s)) } @@ -1437,10 +1407,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .emit(); } - if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk { - self.check_late_bound_lifetime_defs(generic_params); - } - if let FnKind::Fn( _, _, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 89ba6f936d1..3af2ef4e727 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -11,6 +11,8 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi; +use crate::errors::ForbiddenLifetimeBound; + macro_rules! gate_feature_fn { ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{ let (visitor, has_feature, span, name, explain, help) = @@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> { } ImplTraitVisitor { vis: self }.visit_ty(ty); } + + fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) { + // Check only lifetime parameters are present and that the lifetime + // parameters that are present have no bounds. + let non_lt_param_spans: Vec<_> = params + .iter() + .filter_map(|param| match param.kind { + ast::GenericParamKind::Lifetime { .. } => None, + _ => Some(param.ident.span), + }) + .collect(); + // FIXME: gate_feature_post doesn't really handle multispans... + if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders { + feature_err( + &self.sess.parse_sess, + sym::non_lifetime_binders, + non_lt_param_spans, + rustc_errors::fluent::ast_passes_forbidden_non_lifetime_param, + ) + .emit(); + } + for param in params { + if !param.bounds.is_empty() { + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + self.sess.emit_err(ForbiddenLifetimeBound { spans }); + } + } + } } impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { @@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { .. }) = attr_info { - gate_feature_fn!(self, has_feature, attr.span, *name, descr); + gate_feature_fn!(self, has_feature, attr.span, *name, *descr); } // Check unstable flavors of the `#[doc]` attribute. if attr.has_name(sym::doc) { @@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::TyKind::BareFn(bare_fn_ty) => { // Function pointers cannot be `const` self.check_extern(bare_fn_ty.ext, ast::Const::No); + self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params); } ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental"); @@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_ty(self, ty) } + fn visit_generics(&mut self, g: &'a ast::Generics) { + for predicate in &g.where_clause.predicates { + match predicate { + ast::WherePredicate::BoundPredicate(bound_pred) => { + // A type binding, eg `for<'c> Foo: Send+Clone+'c` + self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); + } + _ => {} + } + } + visit::walk_generics(self, g); + } + fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) { if let ast::FnRetTy::Ty(output_ty) = ret_ty { if let ast::TyKind::Never = output_ty.kind { @@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_pat(self, pattern) } + fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) { + self.check_late_bound_lifetime_defs(&t.bound_generic_params); + visit::walk_poly_trait_ref(self, t); + } + fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { if let Some(header) = fn_kind.header() { // Stability of const fn methods are covered in `visit_assoc_item` below. self.check_extern(header.ext, header.constness); } + if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind { + self.check_late_bound_lifetime_defs(generic_params); + } + if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() { gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 40531c1c164..3d240108b4a 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -731,7 +731,7 @@ pub fn eval_condition( sess, sym::cfg_target_compact, cfg.span, - &"compact `cfg(target(..))` is experimental and subject to change" + "compact `cfg(target(..))` is experimental and subject to change" ).emit(); } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index a6afbad5b24..0432a9c5a12 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -286,6 +286,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("mutable-globals", Some(sym::wasm_target_feature)), ("nontrapping-fptoint", Some(sym::wasm_target_feature)), ("reference-types", Some(sym::wasm_target_feature)), + ("relaxed-simd", Some(sym::wasm_target_feature)), ("sign-ext", Some(sym::wasm_target_feature)), ("simd128", None), // tidy-alphabetical-end diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 5267f73efc8..7122ccdcd2e 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -473,6 +473,8 @@ declare_features! ( (active, no_sanitize, "1.42.0", Some(39699), None), /// Allows using the `non_exhaustive_omitted_patterns` lint. (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), + /// Allows `for` binders in where-clauses + (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(1), None), /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index e5c176f19ea..221721f5909 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -14,7 +14,7 @@ use crate::errors::{ AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, }; -use crate::middle::resolve_lifetime as rl; +use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -225,10 +225,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id)); - match tcx.named_region(lifetime.hir_id) { - Some(rl::Region::Static) => tcx.lifetimes.re_static, + match tcx.named_bound_var(lifetime.hir_id) { + Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static, - Some(rl::Region::LateBound(debruijn, index, def_id)) => { + Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => { let name = lifetime_name(def_id.expect_local()); let br = ty::BoundRegion { var: ty::BoundVar::from_u32(index), @@ -237,7 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.mk_re_late_bound(debruijn, br) } - Some(rl::Region::EarlyBound(def_id)) => { + Some(rbv::ResolvedArg::EarlyBound(def_id)) => { let name = tcx.hir().ty_param_name(def_id.expect_local()); let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); let generics = tcx.generics_of(item_def_id); @@ -245,7 +245,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name }) } - Some(rl::Region::Free(scope, id)) => { + Some(rbv::ResolvedArg::Free(scope, id)) => { let name = lifetime_name(id.expect_local()); tcx.mk_re_free(scope, ty::BrNamed(id, name)) @@ -1607,7 +1607,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(lifetime, None) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { - if tcx.named_region(lifetime.hir_id).is_some() { + if tcx.named_bound_var(lifetime.hir_id).is_some() { self.ast_region_to_region(lifetime, None) } else { self.re_infer(None, span).unwrap_or_else(|| { @@ -2600,6 +2600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, opt_self_ty: Option>, path: &hir::Path<'_>, + hir_id: hir::HirId, permit_variants: bool, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -2663,11 +2664,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }); - let def_id = def_id.expect_local(); - let item_def_id = tcx.hir().ty_param_owner(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) + match tcx.named_bound_var(hir_id) { + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { + let name = + tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); + let br = ty::BoundTy { + var: ty::BoundVar::from_u32(index), + kind: ty::BoundTyKind::Param(def_id, name), + }; + tcx.mk_ty(ty::Bound(debruijn, br)) + } + Some(rbv::ResolvedArg::EarlyBound(_)) => { + let def_id = def_id.expect_local(); + let item_def_id = tcx.hir().ty_param_owner(def_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id.to_def_id()]; + tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) + } + arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), + } } Res::SelfTyParam { .. } => { // `Self` in trait or type alias. @@ -2870,14 +2885,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn( + let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn( ast_ty.hir_id, bf.unsafety, bf.abi, bf.decl, None, Some(ast_ty), - )) + )); + + if let Some(guar) = + deny_non_region_late_bound(tcx, bf.generic_params, "function pointer") + { + tcx.ty_error_with_guaranteed(guar) + } else { + fn_ptr_ty + } } hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.maybe_lint_bare_trait(ast_ty, in_path); @@ -2885,12 +2908,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::DynStar => ty::DynStar, }; - self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr) + + let object_ty = self.conv_object_ty_poly_trait_ref( + ast_ty.span, + bounds, + lifetime, + borrowed, + repr, + ); + + if let Some(guar) = bounds.iter().find_map(|trait_ref| { + deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object") + }) { + tcx.ty_error_with_guaranteed(guar) + } else { + object_ty + } } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); - self.res_to_ty(opt_self_ty, path, false) + self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false) } &hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => { let opaque_ty = tcx.hir().item(item_id); @@ -3346,3 +3384,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } + +fn deny_non_region_late_bound( + tcx: TyCtxt<'_>, + params: &[hir::GenericParam<'_>], + where_: &str, +) -> Option { + params.iter().find_map(|bad_param| { + let what = match bad_param.kind { + hir::GenericParamKind::Type { .. } => "type", + hir::GenericParamKind::Const { .. } => "const", + hir::GenericParamKind::Lifetime { .. } => return None, + }; + + let mut diag = tcx.sess.struct_span_err( + bad_param.span, + format!("late-bound {what} parameter not allowed on {where_} types"), + ); + + Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() }) + }) +} diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 456c5bc99b7..8ebe576a224 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -41,8 +41,8 @@ use std::iter; mod generics_of; mod item_bounds; -mod lifetimes; mod predicates_of; +mod resolve_bound_vars; mod type_of; /////////////////////////////////////////////////////////////////////////// @@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { } pub fn provide(providers: &mut Providers) { - lifetimes::provide(providers); + resolve_bound_vars::provide(providers); *providers = Providers { opt_const_param_of: type_of::opt_const_param_of, type_of: type_of::type_of, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 014ee9fcc20..7bcaeadbcf6 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -1,4 +1,4 @@ -use crate::middle::resolve_lifetime as rl; +use crate::middle::resolve_bound_vars as rbv; use hir::{ intravisit::{self, Visitor}, GenericParamKind, HirId, Node, @@ -394,10 +394,11 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option {} - Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {} - Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => { + match self.tcx.named_bound_var(lt.hir_id) { + Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {} + Some(rbv::ResolvedArg::LateBound(debruijn, _, _)) + if debruijn < self.outer_index => {} + Some(rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..)) | None => { self.has_late_bound_regions = Some(lt.ident.span); } } diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs similarity index 86% rename from compiler/rustc_hir_analysis/src/collect/lifetimes.rs rename to compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index d8606f759b2..8c388040fbf 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -16,7 +16,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::resolve_lifetime::*; +use rustc_middle::middle::resolve_bound_vars::*; use rustc_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable}; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; @@ -24,59 +24,61 @@ use rustc_span::Span; use std::fmt; trait RegionExt { - fn early(param: &GenericParam<'_>) -> (LocalDefId, Region); + fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); - fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, Region); + fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); fn id(&self) -> Option; - fn shifted(self, amount: u32) -> Region; + fn shifted(self, amount: u32) -> ResolvedArg; } -impl RegionExt for Region { - fn early(param: &GenericParam<'_>) -> (LocalDefId, Region) { - debug!("Region::early: def_id={:?}", param.def_id); - (param.def_id, Region::EarlyBound(param.def_id.to_def_id())) +impl RegionExt for ResolvedArg { + fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { + debug!("ResolvedArg::early: def_id={:?}", param.def_id); + (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id())) } - fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, Region) { + fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { let depth = ty::INNERMOST; debug!( - "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}", + "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}", idx, param, depth, param.def_id, ); - (param.def_id, Region::LateBound(depth, idx, param.def_id.to_def_id())) + (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id())) } fn id(&self) -> Option { match *self { - Region::Static => None, + ResolvedArg::StaticLifetime => None, - Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id), + ResolvedArg::EarlyBound(id) + | ResolvedArg::LateBound(_, _, id) + | ResolvedArg::Free(_, id) => Some(id), } } - fn shifted(self, amount: u32) -> Region { + fn shifted(self, amount: u32) -> ResolvedArg { match self { - Region::LateBound(debruijn, idx, id) => { - Region::LateBound(debruijn.shifted_in(amount), idx, id) + ResolvedArg::LateBound(debruijn, idx, id) => { + ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id) } _ => self, } } } -/// Maps the id of each lifetime reference to the lifetime decl +/// Maps the id of each bound variable reference to the variable decl /// that it corresponds to. /// -/// FIXME. This struct gets converted to a `ResolveLifetimes` for +/// FIXME. This struct gets converted to a `ResolveBoundVars` for /// actual use. It has the same data, but indexed by `LocalDefId`. This /// is silly. #[derive(Debug, Default)] -struct NamedRegionMap { - // maps from every use of a named (not anonymous) lifetime to a - // `Region` describing how that region is bound - defs: HirIdMap, +struct NamedVarMap { + // maps from every use of a named (not anonymous) bound var to a + // `ResolvedArg` describing how that variable is bound + defs: HirIdMap, // Maps relevant hir items to the bound vars on them. These include: // - function defs @@ -87,9 +89,9 @@ struct NamedRegionMap { late_bound_vars: HirIdMap>, } -struct LifetimeContext<'a, 'tcx> { +struct BoundVarContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, - map: &'a mut NamedRegionMap, + map: &'a mut NamedVarMap, scope: ScopeRef<'a>, } @@ -102,7 +104,7 @@ enum Scope<'a> { Binder { /// We use an IndexMap here because we want these lifetimes in order /// for diagnostics. - lifetimes: FxIndexMap, + bound_vars: FxIndexMap, scope_type: BinderScopeType, @@ -141,7 +143,7 @@ enum Scope<'a> { /// inferred in a function body or potentially error outside one), /// for the default choice of lifetime in a trait object type. ObjectLifetimeDefault { - lifetime: Option, + lifetime: Option, s: ScopeRef<'a>, }, @@ -150,7 +152,7 @@ enum Scope<'a> { /// lifetimes encountered when identifying the trait that an associated type /// is declared on. Supertrait { - lifetimes: Vec, + bound_vars: Vec, s: ScopeRef<'a>, }, @@ -185,9 +187,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>); impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { - Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f + Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f .debug_struct("Binder") - .field("lifetimes", lifetimes) + .field("bound_vars", bound_vars) .field("scope_type", scope_type) .field("hir_id", hir_id) .field("where_bound_origin", where_bound_origin) @@ -202,9 +204,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("lifetime", lifetime) .field("s", &"..") .finish(), - Scope::Supertrait { lifetimes, s: _ } => f + Scope::Supertrait { bound_vars, s: _ } => f .debug_struct("Supertrait") - .field("lifetimes", lifetimes) + .field("bound_vars", bound_vars) .field("s", &"..") .finish(), Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), @@ -219,27 +221,27 @@ type ScopeRef<'a> = &'a Scope<'a>; pub(crate) fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { - resolve_lifetimes, + resolve_bound_vars, - named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id), + named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id), is_late_bound_map, object_lifetime_default, - late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id), + late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id), ..*providers }; } -/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`. +/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`. /// You should not read the result of this query directly, but rather use -/// `named_region_map`, `is_late_bound_map`, etc. +/// `named_variable_map`, `is_late_bound_map`, etc. #[instrument(level = "debug", skip(tcx))] -fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes { - let mut named_region_map = - NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() }; - let mut visitor = LifetimeContext { +fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars { + let mut named_variable_map = + NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() }; + let mut visitor = BoundVarContext { tcx, - map: &mut named_region_map, + map: &mut named_variable_map, scope: &Scope::Root { opt_parent_item: None }, }; match tcx.hir().owner(local_def_id) { @@ -260,13 +262,13 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife hir::OwnerNode::Crate(_) => {} } - let mut rl = ResolveLifetimes::default(); + let mut rl = ResolveBoundVars::default(); - for (hir_id, v) in named_region_map.defs { + for (hir_id, v) in named_variable_map.defs { let map = rl.defs.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } - for (hir_id, v) in named_region_map.late_bound_vars { + for (hir_id, v) in named_variable_map.late_bound_vars { let map = rl.late_bound_vars.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } @@ -276,21 +278,33 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife rl } -fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind { - match region { - Region::LateBound(_, _, def_id) => { +fn late_arg_as_bound_arg<'tcx>( + tcx: TyCtxt<'tcx>, + arg: &ResolvedArg, + param: &GenericParam<'tcx>, +) -> ty::BoundVariableKind { + match arg { + ResolvedArg::LateBound(_, _, def_id) => { let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); - ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + match param.kind { + GenericParamKind::Lifetime { .. } => { + ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + } + GenericParamKind::Type { .. } => { + ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name)) + } + GenericParamKind::Const { .. } => ty::BoundVariableKind::Const, + } } - _ => bug!("{:?} is not a late region", region), + _ => bug!("{:?} is not a late argument", arg), } } -impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { +impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref. fn poly_trait_ref_binder_info(&mut self) -> (Vec, BinderScopeType) { let mut scope = self.scope; - let mut supertrait_lifetimes = vec![]; + let mut supertrait_bound_vars = vec![]; loop { match scope { Scope::Body { .. } | Scope::Root { .. } => { @@ -301,14 +315,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } - Scope::Supertrait { s, lifetimes } => { - supertrait_lifetimes = lifetimes.clone(); + Scope::Supertrait { s, bound_vars } => { + supertrait_bound_vars = bound_vars.clone(); scope = s; } Scope::TraitRefBoundary { .. } => { // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_lifetimes.is_empty()); + assert!(supertrait_bound_vars.is_empty()); break (vec![], BinderScopeType::Normal); } @@ -316,14 +330,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // Nested poly trait refs have the binders concatenated let mut full_binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_lifetimes.into_iter()); + full_binders.extend(supertrait_bound_vars.into_iter()); break (full_binders, BinderScopeType::Concatenating); } } } } } -impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; fn nested_visit_map(&mut self) -> Self::Map { @@ -386,14 +400,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } - let (lifetimes, binders): (FxIndexMap, Vec<_>) = + let (bound_vars, binders): (FxIndexMap, Vec<_>) = bound_generic_params .iter() - .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) .enumerate() .map(|(late_bound_idx, param)| { - let pair = Region::late(late_bound_idx as u32, param); - let r = late_region_as_bound_region(self.tcx, &pair.1); + let pair = ResolvedArg::late(late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); (pair, r) }) .unzip(); @@ -401,7 +414,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.record_late_bound_vars(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, - lifetimes, + bound_vars, s: self.scope, scope_type: BinderScopeType::Normal, where_bound_origin: None, @@ -461,7 +474,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // conservatively add all resolved lifetimes. Otherwise we run into problems in // cases like `type Foo<'a> = impl Bar`. let parent_item = self.tcx.hir().get_parent_item(item.hir_id()); - let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item); + let resolved_lifetimes: &ResolveBoundVars = + self.tcx.resolve_bound_vars(parent_item); // We need to add *all* deps, since opaque tys may want them from *us* for (&owner, defs) in resolved_lifetimes.defs.iter() { defs.iter().for_each(|(&local_id, region)| { @@ -478,35 +492,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } hir::ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_), + origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent), generics, .. }) => { // We want to start our early-bound indices at the end of the parent scope, // not including any parent `impl Trait`s. - let mut lifetimes = FxIndexMap::default(); + let mut bound_vars = FxIndexMap::default(); debug!(?generics.params); for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => { - let (def_id, reg) = Region::early(¶m); - lifetimes.insert(def_id, reg); - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {} - } + let (def_id, reg) = ResolvedArg::early(¶m); + bound_vars.insert(def_id, reg); } - let scope = Scope::Binder { - hir_id: item.hir_id(), - lifetimes, - s: self.scope, - scope_type: BinderScopeType::Normal, - where_bound_origin: None, - }; + let scope = Scope::Root { opt_parent_item: Some(parent) }; self.with(scope, |this| { - let scope = Scope::TraitRefBoundary { s: this.scope }; - this.with(scope, |this| intravisit::walk_item(this, item)) - }); + let scope = Scope::Binder { + hir_id: item.hir_id(), + bound_vars, + s: this.scope, + scope_type: BinderScopeType::Normal, + where_bound_origin: None, + }; + this.with(scope, |this| { + let scope = Scope::TraitRefBoundary { s: this.scope }; + this.with(scope, |this| intravisit::walk_item(this, item)) + }); + }) } hir::ItemKind::TyAlias(_, generics) | hir::ItemKind::Enum(_, generics) @@ -516,18 +528,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | hir::ItemKind::TraitAlias(generics, ..) | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(Region::early(param)), - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, - }) - .collect(); + let bound_vars = generics.params.iter().map(ResolvedArg::early).collect(); self.record_late_bound_vars(item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: item.hir_id(), - lifetimes, + bound_vars, scope_type: BinderScopeType::Normal, s: self.scope, where_bound_origin: None, @@ -562,21 +567,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { match ty.kind { hir::TyKind::BareFn(c) => { - let (lifetimes, binders): (FxIndexMap, Vec<_>) = c + let (bound_vars, binders): (FxIndexMap, Vec<_>) = c .generic_params .iter() - .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) .enumerate() .map(|(late_bound_idx, param)| { - let pair = Region::late(late_bound_idx as u32, param); - let r = late_region_as_bound_region(self.tcx, &pair.1); + let pair = ResolvedArg::late(late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); (pair, r) }) .unzip(); self.record_late_bound_vars(ty.hir_id, binders); let scope = Scope::Binder { hir_id: ty.hir_id, - lifetimes, + bound_vars, s: self.scope, scope_type: BinderScopeType::Normal, where_bound_origin: None, @@ -674,7 +678,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).cloned(); - let Some(Region::LateBound(_, _, def_id)) = def else { + let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; let Some(def_id) = def_id.as_local() else { @@ -722,18 +726,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } Type(bounds, ty) => { let generics = &trait_item.generics; - let lifetimes = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(Region::early(param)), - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, - }) - .collect(); + let bound_vars = generics.params.iter().map(ResolvedArg::early).collect(); self.record_late_bound_vars(trait_item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: trait_item.hir_id(), - lifetimes, + bound_vars, s: self.scope, scope_type: BinderScopeType::Normal, where_bound_origin: None, @@ -768,18 +765,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }), Type(ty) => { let generics = &impl_item.generics; - let lifetimes: FxIndexMap = generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(Region::early(param)), - GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None, - }) - .collect(); + let bound_vars: FxIndexMap = + generics.params.iter().map(ResolvedArg::early).collect(); self.record_late_bound_vars(impl_item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: impl_item.hir_id(), - lifetimes, + bound_vars, s: self.scope, scope_type: BinderScopeType::Normal, where_bound_origin: None, @@ -803,7 +794,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { match lifetime_ref.res { - hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static), + hir::LifetimeName::Static => { + self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime) + } hir::LifetimeName::Param(param_def_id) => { self.resolve_lifetime_ref(param_def_id, lifetime_ref) } @@ -814,13 +807,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } - fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) { for (i, segment) in path.segments.iter().enumerate() { let depth = path.segments.len() - i - 1; if let Some(args) = segment.args { self.visit_segment_args(path.res, depth, args); } } + if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res { + self.resolve_type_ref(param_def_id.expect_local(), hir_id); + } } fn visit_fn( @@ -869,24 +865,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { origin, .. }) => { - let lifetimes: FxIndexMap = + + let (bound_vars, binders): (FxIndexMap, Vec<_>) = bound_generic_params - .iter() - .filter(|param| { - matches!(param.kind, GenericParamKind::Lifetime { .. }) - }) - .enumerate() - .map(|(late_bound_idx, param)| { - Region::late(late_bound_idx as u32, param) - }) - .collect(); - let binders: Vec<_> = - lifetimes - .iter() - .map(|(_, region)| { - late_region_as_bound_region(this.tcx, region) - }) - .collect(); + .iter() + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = ResolvedArg::late(late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(this.tcx, &pair.1, param); + (pair, r) + }) + .unzip(); this.record_late_bound_vars(hir_id, binders.clone()); // Even if there are no lifetimes defined here, we still wrap it in a binder // scope. If there happens to be a nested poly trait ref (an error), that @@ -894,7 +883,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // being wrong. let scope = Scope::Binder { hir_id, - lifetimes, + bound_vars, s: this.scope, scope_type: BinderScopeType::Normal, where_bound_origin: Some(origin), @@ -920,7 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { if lt.res != hir::LifetimeName::Static { continue; } - this.insert_lifetime(lt, Region::Static); + this.insert_lifetime(lt, ResolvedArg::StaticLifetime); this.tcx .sess .struct_span_warn( @@ -964,7 +953,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.record_late_bound_vars(*hir_id, binders); let scope = Scope::Binder { hir_id: *hir_id, - lifetimes: FxIndexMap::default(), + bound_vars: FxIndexMap::default(), s: self.scope, scope_type, where_bound_origin: None, @@ -983,16 +972,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); let initial_bound_vars = binders.len() as u32; - let mut lifetimes: FxIndexMap = FxIndexMap::default(); - let binders_iter = trait_ref - .bound_generic_params - .iter() - .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) - .enumerate() - .map(|(late_bound_idx, param)| { - let pair = Region::late(initial_bound_vars + late_bound_idx as u32, param); - let r = late_region_as_bound_region(self.tcx, &pair.1); - lifetimes.insert(pair.0, pair.1); + let mut bound_vars: FxIndexMap = FxIndexMap::default(); + let binders_iter = + trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| { + let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); + bound_vars.insert(pair.0, pair.1); r }); binders.extend(binders_iter); @@ -1006,7 +991,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // refs. let scope = Scope::Binder { hir_id: trait_ref.trait_ref.hir_ref_id, - lifetimes, + bound_vars, s: self.scope, scope_type, where_bound_origin: None, @@ -1063,13 +1048,13 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifeti } } -impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { +impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { fn with(&mut self, wrap_scope: Scope<'_>, f: F) where - F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>), + F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>), { - let LifetimeContext { tcx, map, .. } = self; - let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope }; + let BoundVarContext { tcx, map, .. } = self; + let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope }; let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); { let _enter = span.enter(); @@ -1110,23 +1095,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { generics: &'tcx hir::Generics<'tcx>, walk: F, ) where - F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>), + F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>), { let mut named_late_bound_vars = 0; - let lifetimes: FxIndexMap = generics + let bound_vars: FxIndexMap = generics .params .iter() - .filter_map(|param| match param.kind { + .map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { if self.tcx.is_late_bound(param.hir_id) { let late_bound_idx = named_late_bound_vars; named_late_bound_vars += 1; - Some(Region::late(late_bound_idx, param)) + ResolvedArg::late(late_bound_idx, param) } else { - Some(Region::early(param)) + ResolvedArg::early(param) } } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { + ResolvedArg::early(param) + } }) .collect(); @@ -1139,14 +1126,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }) .enumerate() .map(|(late_bound_idx, param)| { - let pair = Region::late(late_bound_idx as u32, param); - late_region_as_bound_region(self.tcx, &pair.1) + let pair = ResolvedArg::late(late_bound_idx as u32, param); + late_arg_as_bound_arg(self.tcx, &pair.1, param) }) .collect(); self.record_late_bound_vars(hir_id, binders); let scope = Scope::Binder { hir_id, - lifetimes, + bound_vars, s: self.scope, scope_type: BinderScopeType::Normal, where_bound_origin: None, @@ -1177,15 +1164,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root { opt_parent_item } => { if let Some(parent_item) = opt_parent_item && let parent_generics = self.tcx.generics_of(parent_item) - && parent_generics.param_def_id_to_index.contains_key(®ion_def_id.to_def_id()) + && parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some() { - break Some(Region::EarlyBound(region_def_id.to_def_id())); + break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id())); } break None; } - Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => { - if let Some(&def) = lifetimes.get(®ion_def_id) { + Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => { + if let Some(&def) = bound_vars.get(®ion_def_id) { break Some(def.shifted(late_depth)); } match scope_type { @@ -1259,7 +1246,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; if let Some(mut def) = result { - if let Region::EarlyBound(..) = def { + if let ResolvedArg::EarlyBound(..) = def { // Do not free early-bound regions, only late-bound ones. } else if let Some(body_id) = outermost_body { let fn_id = self.tcx.hir().body_owner(body_id); @@ -1275,10 +1262,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { kind: hir::ImplItemKind::Fn(..), .. }) => { - def = Region::Free(owner_id.to_def_id(), def.id().unwrap()); + def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap()); } Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => { - def = Region::Free(closure.def_id.to_def_id(), def.id().unwrap()); + def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap()); } _ => {} } @@ -1329,6 +1316,57 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { ); } + fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) { + // Walk up the scope chain, tracking the number of fn scopes + // that we pass through, until we find a lifetime with the + // given name or we run out of scopes. + // search. + let mut late_depth = 0; + let mut scope = self.scope; + let result = loop { + match *scope { + Scope::Body { s, .. } => { + scope = s; + } + + Scope::Root { opt_parent_item } => { + if let Some(parent_item) = opt_parent_item + && let parent_generics = self.tcx.generics_of(parent_item) + && parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some() + { + break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id())); + } + break None; + } + + Scope::Binder { ref bound_vars, scope_type, s, .. } => { + if let Some(&def) = bound_vars.get(¶m_def_id) { + break Some(def.shifted(late_depth)); + } + match scope_type { + BinderScopeType::Normal => late_depth += 1, + BinderScopeType::Concatenating => {} + } + scope = s; + } + + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } => { + scope = s; + } + } + }; + + if let Some(def) = result { + self.map.defs.insert(hir_id, def); + return; + } + + span_bug!(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}",); + } + #[instrument(level = "debug", skip(self))] fn visit_segment_args( &mut self, @@ -1415,10 +1453,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if in_body { None } else { - Some(Region::Static) + Some(ResolvedArg::StaticLifetime) } } - ObjectLifetimeDefault::Static => Some(Region::Static), + ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime), ObjectLifetimeDefault::Param(param_def_id) => { // This index can be used with `generic_args` since `parent_count == 0`. let index = generics.param_def_id_to_index[¶m_def_id] as usize; @@ -1507,18 +1545,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // in the trait ref `YY<...>` in `Item: YY<...>`. for binding in generic_args.bindings { let scope = Scope::ObjectLifetimeDefault { - lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) }, + lifetime: if has_lifetime_parameter { + None + } else { + Some(ResolvedArg::StaticLifetime) + }, s: self.scope, }; if let Some(type_def_id) = type_def_id { - let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes( - self.tcx, - type_def_id, - binding.ident, - ); + let bound_vars = + BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident); self.with(scope, |this| { let scope = Scope::Supertrait { - lifetimes: lifetimes.unwrap_or_default(), + bound_vars: bound_vars.unwrap_or_default(), s: this.scope, }; this.with(scope, |this| this.visit_assoc_type_binding(binding)); @@ -1541,7 +1580,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// ``` /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on /// the starting trait `Bar`, we would return `Some(['b, 'a])`. - fn supertrait_hrtb_lifetimes( + fn supertrait_hrtb_vars( tcx: TyCtxt<'tcx>, def_id: DefId, assoc_name: Ident, @@ -1626,7 +1665,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } - Scope::Root { .. } | Scope::Elision { .. } => break Region::Static, + Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime, Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, @@ -1641,7 +1680,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) { + fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) { debug!(span = ?lifetime_ref.ident.span); self.map.defs.insert(lifetime_ref.hir_id, def); } @@ -1649,7 +1688,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// Sometimes we resolve a lifetime, but later find that it is an /// error (esp. around impl trait). In that case, we remove the /// entry into `map.defs` so as not to confuse later code. - fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) { + fn uninsert_lifetime_on_error( + &mut self, + lifetime_ref: &'tcx hir::Lifetime, + bad_def: ResolvedArg, + ) { let old_value = self.map.defs.remove(&lifetime_ref.hir_id); assert_eq!(old_value, Some(bad_def)); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index d13d8ff8270..0aa5b075d19 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -477,14 +477,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about. // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of // that struct type. - let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_def_id) { + let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) { self.tcx.mk_trait_ref( - obligation.impl_def_id, - ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_def_id), + obligation.impl_or_alias_def_id, + ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_or_alias_def_id), ) } else { self.tcx - .impl_trait_ref(obligation.impl_def_id) + .impl_trait_ref(obligation.impl_or_alias_def_id) .map(|impl_def| impl_def.skip_binder()) // It is possible that this is absent. In this case, we make no progress. .ok_or(expr)? @@ -494,7 +494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty(); let impl_predicates: ty::GenericPredicates<'tcx> = - self.tcx.predicates_of(obligation.impl_def_id); + self.tcx.predicates_of(obligation.impl_or_alias_def_id); let Some(impl_predicate_index) = obligation.impl_def_predicate_index else { // We don't have the index, so we can only guess. return Err(expr); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 63b170a3c63..69a7235802b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1740,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match *qpath { QPath::Resolved(ref maybe_qself, ref path) => { let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw); - let ty = self.astconv().res_to_ty(self_ty, path, true); + let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true); (path.res, self.handle_raw_ty(path_span, ty)) } QPath::TypeRelative(ref qself, ref segment) => { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index a35fa008a95..a805dad062e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1576,7 +1576,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { traits::ImplDerivedObligation(Box::new( traits::ImplDerivedObligationCause { derived, - impl_def_id, + impl_or_alias_def_id: impl_def_id, impl_def_predicate_index: None, span, }, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 54890489f8b..ef30cd55c0e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ObligationCauseCode::ImplDerivedObligation(data) if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) => { - Some((p, parent, data.impl_def_id, data)) + Some((p, parent, data.impl_or_alias_def_id, data)) } _ => None, }) @@ -714,7 +714,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } Some(Node::Item(hir::Item { - ident, kind: hir::ItemKind::Trait(..), .. + ident, + kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), + .. })) => { skip_list.insert(p); let entry = spanned_predicates.entry(ident.span); diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 964222307bc..f5504b05dc4 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -125,11 +125,11 @@ impl<'tcx> InferCtxt<'tcx> { } (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => { - relation.register_type_equate_obligation(a.into(), b.into()); + relation.register_type_equate_obligation(a, b); Ok(b) } (_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => { - relation.register_type_equate_obligation(b.into(), a.into()); + relation.register_type_equate_obligation(b, a); Ok(a) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 39f4d502259..4fe6c6618f6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -2,7 +2,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::resolve_lifetime as rl; +use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::{self, Region, TyCtxt}; /// This function calls the `visit_ty` method for the parameters @@ -99,11 +99,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { hir::TyKind::Ref(ref lifetime, _) => { // the lifetime of the Ref let hir_id = lifetime.hir_id; - match (self.tcx.named_region(hir_id), self.bound_region) { + match (self.tcx.named_bound_var(hir_id), self.bound_region) { // Find the index of the named region that was part of the // error. We will then search the function parameters for a bound // region at the right depth with the same index - (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => { + (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id == def_id { self.found_type = Some(arg); @@ -115,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBound(debruijn_index, _, id)), + Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _), ) => { debug!( @@ -131,10 +131,10 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { ( Some( - rl::Region::Static - | rl::Region::Free(_, _) - | rl::Region::EarlyBound(_) - | rl::Region::LateBound(_, _, _), + rbv::ResolvedArg::StaticLifetime + | rbv::ResolvedArg::Free(_, _) + | rbv::ResolvedArg::EarlyBound(_) + | rbv::ResolvedArg::LateBound(_, _, _), ) | None, _, @@ -186,9 +186,9 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { } fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { - match (self.tcx.named_region(lifetime.hir_id), self.bound_region) { + match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! - (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => { + (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id == def_id { self.found_it = true; @@ -196,7 +196,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { } } - (Some(rl::Region::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => { + (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); @@ -208,10 +208,10 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { ( Some( - rl::Region::Static - | rl::Region::EarlyBound(_) - | rl::Region::LateBound(_, _, _) - | rl::Region::Free(_, _), + rbv::ResolvedArg::StaticLifetime + | rbv::ResolvedArg::EarlyBound(_) + | rbv::ResolvedArg::LateBound(_, _, _) + | rbv::ResolvedArg::Free(_, _), ) | None, _, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index e617eb68d47..68b39c5f00f 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -158,7 +158,7 @@ impl<'tcx> Elaborator<'tcx> { traits::ImplDerivedObligation(Box::new( traits::ImplDerivedObligationCause { derived, - impl_def_id: data.def_id(), + impl_or_alias_def_id: data.def_id(), impl_def_predicate_index: Some(index), span, }, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 34cf17d25a9..cd793d36de6 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2007,7 +2007,7 @@ impl ExplicitOutlivesRequirements { inferred_outlives: &[ty::Region<'tcx>], predicate_span: Span, ) -> Vec<(usize, Span)> { - use rustc_middle::middle::resolve_lifetime::Region; + use rustc_middle::middle::resolve_bound_vars::ResolvedArg; bounds .iter() @@ -2017,8 +2017,8 @@ impl ExplicitOutlivesRequirements { return None; }; - let is_inferred = match tcx.named_region(lifetime.hir_id) { - Some(Region::EarlyBound(def_id)) => inferred_outlives + let is_inferred = match tcx.named_bound_var(lifetime.hir_id) { + Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives .iter() .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })), _ => false, @@ -2097,7 +2097,7 @@ impl ExplicitOutlivesRequirements { impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - use rustc_middle::middle::resolve_lifetime::Region; + use rustc_middle::middle::resolve_bound_vars::ResolvedArg; let def_id = item.owner_id.def_id; if let hir::ItemKind::Struct(_, hir_generics) @@ -2120,8 +2120,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { let (relevant_lifetimes, bounds, predicate_span, in_where_clause) = match where_predicate { hir::WherePredicate::RegionPredicate(predicate) => { - if let Some(Region::EarlyBound(region_def_id)) = - cx.tcx.named_region(predicate.lifetime.hir_id) + if let Some(ResolvedArg::EarlyBound(region_def_id)) = + cx.tcx.named_bound_var(predicate.lifetime.hir_id) { ( Self::lifetimes_outliving_lifetime( diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 43047051f0f..e941dd45688 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1541,8 +1541,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.impl_defaultness.set_some(def_id.index, *defaultness); self.tables.constness.set_some(def_id.index, *constness); - let trait_ref = self.tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder); + let trait_ref = self.tcx.impl_trait_ref(def_id); if let Some(trait_ref) = trait_ref { + let trait_ref = trait_ref.skip_binder(); let trait_def = self.tcx.trait_def(trait_ref.def_id); if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) { if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9227609cc8b..a9fb8b246c6 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -18,7 +18,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::metadata::ModChild; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; -use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; +use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 8dc68b1f5a8..0b6774f1b1f 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -29,7 +29,7 @@ pub mod lib_features { pub mod limits; pub mod privacy; pub mod region; -pub mod resolve_lifetime; +pub mod resolve_bound_vars; pub mod stability; pub fn provide(providers: &mut crate::ty::query::Providers) { diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs similarity index 83% rename from compiler/rustc_middle/src/middle/resolve_lifetime.rs rename to compiler/rustc_middle/src/middle/resolve_bound_vars.rs index c3bf1c717d9..b96d07e7dc8 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -1,4 +1,4 @@ -//! Name resolution for lifetimes: type declarations. +//! Name resolution for lifetimes and late-bound type and const variables: type declarations. use crate::ty; @@ -8,10 +8,10 @@ use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] -pub enum Region { - Static, - EarlyBound(/* lifetime decl */ DefId), - LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId), +pub enum ResolvedArg { + StaticLifetime, + EarlyBound(/* decl */ DefId), + LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId), Free(DefId, /* lifetime decl */ DefId), } @@ -46,10 +46,10 @@ pub enum ObjectLifetimeDefault { /// Maps the id of each lifetime reference to the lifetime decl /// that it corresponds to. #[derive(Default, HashStable, Debug)] -pub struct ResolveLifetimes { +pub struct ResolveBoundVars { /// Maps from every use of a named (not anonymous) lifetime to a /// `Region` describing how that region is bound - pub defs: FxHashMap>, + pub defs: FxHashMap>, pub late_bound_vars: FxHashMap>>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4b34f6b4881..6f878a955fa 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -781,7 +781,7 @@ rustc_queries! { separate_provide_extern } - query issue33140_self_ty(key: DefId) -> Option> { + query issue33140_self_ty(key: DefId) -> Option>> { desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) } } @@ -1641,12 +1641,12 @@ rustc_queries! { /// Does lifetime resolution on items. Importantly, we can't resolve /// lifetimes directly on things like trait methods, because of trait params. /// See `rustc_resolve::late::lifetimes for details. - query resolve_lifetimes(_: hir::OwnerId) -> &'tcx ResolveLifetimes { + query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars { arena_cache desc { "resolving lifetimes" } } - query named_region_map(_: hir::OwnerId) -> - Option<&'tcx FxHashMap> { + query named_variable_map(_: hir::OwnerId) -> + Option<&'tcx FxHashMap> { desc { "looking up a named region" } } query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet> { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c528929e756..6231dd9b6f5 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -474,7 +474,11 @@ pub enum WellFormedLoc { #[derive(TypeVisitable, TypeFoldable)] pub struct ImplDerivedObligationCause<'tcx> { pub derived: DerivedObligationCause<'tcx>, - pub impl_def_id: DefId, + /// The `DefId` of the `impl` that gave rise to the `derived` obligation. + /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl, + /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle + /// that exceptional case where appropriate. + pub impl_or_alias_def_id: DefId, /// The index of the derived predicate in the parent impl's predicates. pub impl_def_predicate_index: Option, pub span: Span, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 927f18f59b9..c7268d561e5 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,7 +1,9 @@ +use crate::middle::resolve_bound_vars as rbv; use crate::mir::interpret::LitToConstInput; use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; use std::fmt; @@ -125,16 +127,27 @@ impl<'tcx> Const<'tcx> { } } - use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; match expr.kind { - ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { - // Find the name and index of the const parameter by indexing the generics of - // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); - Some(tcx.mk_const(ty::ParamConst::new(index, name), ty)) + hir::ExprKind::Path(hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }, + )) => { + match tcx.named_bound_var(expr.hir_id) { + Some(rbv::ResolvedArg::EarlyBound(_)) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let item_def_id = tcx.parent(def_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id]; + let name = tcx.item_name(def_id); + Some(tcx.mk_const(ty::ParamConst::new(index, name), ty)) + } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const( + ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)), + ty, + )), + arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), + } } _ => None, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b37c3e5cf2c..d5be23d2b98 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -9,7 +9,7 @@ use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::struct_lint_level; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; -use crate::middle::resolve_lifetime; +use crate::middle::resolve_bound_vars; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstAllocation}; use crate::mir::{ @@ -2368,9 +2368,9 @@ impl<'tcx> TyCtxt<'tcx> { Some(&*candidates) } - pub fn named_region(self, id: HirId) -> Option { + pub fn named_bound_var(self, id: HirId) -> Option { debug!(?id, "named_region"); - self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) + self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) } pub fn is_late_bound(self, id: HirId) -> bool { diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 9afa37e9ef3..106ce9990e1 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -290,7 +290,7 @@ impl DeepRejectCtxt { // Impls cannot contain these types as these cannot be named directly. ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false, - ty::Placeholder(..) => false, + ty::Placeholder(..) | ty::Bound(..) => false, // Depending on the value of `treat_obligation_params`, we either // treat generic parameters like placeholders or like inference variables. @@ -310,7 +310,7 @@ impl DeepRejectCtxt { ty::Error(_) => true, - ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Bound(..) => { + ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { bug!("unexpected obligation type: {:?}", obligation_ty) } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 303675d3ca5..8849e7eab33 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! { crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::exported_symbols::SymbolExportInfo, - crate::middle::resolve_lifetime::ObjectLifetimeDefault, + crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::AssocItemContainer, ty::DeducedParamAttrs, diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 5c45cc389ee..431f3a5a000 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -8,7 +8,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; use crate::middle::privacy::EffectiveVisibilities; -use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes}; +use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; use crate::mir::interpret::GlobalId; diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index 7d127032179..1b3ac78fbc6 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -47,8 +47,7 @@ fn has_back_edge( return false; } // Check if any of the dominators of the node are also the node's successor. - doms.dominators(node) - .any(|dom| node_data.terminator().successors().into_iter().any(|succ| succ == dom)) + doms.dominators(node).any(|dom| node_data.terminator().successors().any(|succ| succ == dom)) } fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) { diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 65c15d9c674..c1e7f62dea5 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -2,7 +2,7 @@ use either::Either; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; -use rustc_middle::middle::resolve_lifetime::Set1; +use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, TyCtxt}; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 225095948af..7cff8996d24 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -18,7 +18,7 @@ use rustc_hir::{ }; use rustc_hir::{MethodKind, Target, Unsafety}; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; +use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{ParamEnv, TyCtxt}; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4675bd79c46..0a0c94e1dfb 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -270,10 +270,11 @@ where | ty::Ref(..) | ty::FnPtr(..) | ty::Param(..) + | ty::Bound(..) | ty::Error(_) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {} - ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { + ty::Placeholder(..) | ty::Infer(..) => { bug!("unexpected type: {:?}", ty) } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d3bcbbabf55..324de7461cd 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -21,7 +21,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; -use rustc_middle::middle::resolve_lifetime::Set1; +use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::ty::DefIdTree; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; @@ -2505,7 +2505,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let res = match kind { ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()), - NormalRibKind => Res::Err, + NormalRibKind => { + if self.r.session.features_untracked().non_lifetime_binders { + Res::Def(def_kind, def_id.to_def_id()) + } else { + Res::Err + } + } _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind), }; self.r.record_partial_res(param.id, PartialRes::new(res)); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 093698f3b35..bd32adbbdbb 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse; use crate::parse::ParseSess; use rustc_ast::token; use rustc_ast::util::literal::LitError; -use rustc_errors::MultiSpan; +use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan}; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; @@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> { pub cgu_name: &'a str, } -#[derive(Diagnostic)] -#[diag(session_feature_gate_error, code = "E0658")] -pub struct FeatureGateError<'a> { - #[primary_span] +pub struct FeatureGateError { pub span: MultiSpan, - pub explain: &'a str, + pub explain: DiagnosticMessage, +} + +impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError { + #[track_caller] + fn into_diagnostic( + self, + handler: &'a rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'a, T> { + let mut diag = handler.struct_diagnostic(self.explain); + diag.set_span(self.span); + diag.code(error_code!(E0658)); + diag + } } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 2aa8ca9e4a9..cbdcc5581e5 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -88,7 +88,7 @@ pub fn feature_err<'a>( sess: &'a ParseSess, feature: Symbol, span: impl Into, - explain: &str, + explain: impl Into, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { feature_err_issue(sess, feature, span, GateIssue::Language, explain) } @@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>( feature: Symbol, span: impl Into, issue: GateIssue, - explain: &str, + explain: impl Into, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let span = span.into(); @@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>( .map(|err| err.cancel()); } - let mut err = sess.create_err(FeatureGateError { span, explain }); + let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() }); add_feature_diagnostics_for_issue(&mut err, sess, feature, issue); err } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 56835a2466a..37d2aea42ad 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1016,6 +1016,7 @@ symbols! { non_ascii_idents, non_exhaustive, non_exhaustive_omitted_patterns_lint, + non_lifetime_binders, non_modrs_mods, nontemporal_store, noop_method_borrow, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 52ed64868c0..91d96655b64 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Option<(DefId, SubstsRef<'tcx>)> { let tcx = self.tcx; let param_env = obligation.param_env; - let trait_ref = tcx.erase_late_bound_regions(trait_ref); + let trait_ref = self.instantiate_binder_with_placeholders(trait_ref); let trait_self_ty = trait_ref.self_ty(); let mut self_match_impls = vec![]; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 8041066d5d5..a0c67f480d0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1056,7 +1056,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - let ty = self.tcx.erase_late_bound_regions(self_ty); + let ty = self.instantiate_binder_with_placeholders(self_ty); let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false }; let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; let ty::Param(param) = inner_ty.kind() else { return false }; @@ -3143,7 +3143,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { parent_trait_pred.print_modifiers_and_trait_path() ); let mut is_auto_trait = false; - match self.tcx.hir().get_if_local(data.impl_def_id) { + match self.tcx.hir().get_if_local(data.impl_or_alias_def_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(is_auto, ..), ident, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index e9f7c3bc4cc..dae602908a3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // still be provided by a manual implementation for // this trait and type. } - ty::Param(..) | ty::Alias(ty::Projection, ..) => { + ty::Param(..) + | ty::Alias(ty::Projection, ..) + | ty::Placeholder(..) + | ty::Bound(..) => { // In these cases, we don't know what the actual // type is. Therefore, we cannot break it down // into its constituent types. So we don't @@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); self.infcx.probe(|_snapshot| { + if obligation.has_non_region_late_bound() { + return; + } + // The code below doesn't care about regions, and the // self-ty here doesn't escape this probe, so just erase // any LBR. diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 9770813e86d..0167f402610 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1189,7 +1189,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(|derived| { ImplDerivedObligation(Box::new(ImplDerivedObligationCause { derived, - impl_def_id, + impl_or_alias_def_id: impl_def_id, impl_def_predicate_index: None, span: obligation.cause.span, })) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 27feedc48be..26f869ac1fe 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2657,7 +2657,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = cause.clone().derived_cause(parent_trait_pred, |derived| { ImplDerivedObligation(Box::new(ImplDerivedObligationCause { derived, - impl_def_id: def_id, + impl_or_alias_def_id: def_id, impl_def_predicate_index: Some(index), span, })) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 41e837e8b75..fc3d9fb067d 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,7 +1,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_index::bit_set::BitSet; -use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, +}; use rustc_session::config::TraitSolver; use rustc_span::def_id::{DefId, CRATE_DEF_ID}; use rustc_trait_selection::traits; @@ -355,7 +357,7 @@ fn instance_def_size_estimate<'tcx>( /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`. /// /// See [`ty::ImplOverlapKind::Issue33140`] for more details. -fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { +fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option>> { debug!("issue33140_self_ty({:?})", def_id); let trait_ref = tcx @@ -394,7 +396,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { if self_ty_matches { debug!("issue33140_self_ty - MATCHES!"); - Some(self_ty) + Some(EarlyBinder(self_ty)) } else { debug!("issue33140_self_ty - non-matching self type"); None diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 5a0b8594104..9e3e13e7004 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3502,8 +3502,10 @@ pub trait Iterator { } } - /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those - /// of another. + /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of + /// this [`Iterator`] with those of another. The comparison works like short-circuit + /// evaluation, returning a result without comparing the remaining elements. + /// As soon as an order can be determined, the evaluation stops and a result is returned. /// /// # Examples /// @@ -3513,9 +3515,25 @@ pub trait Iterator { /// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal)); /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less)); /// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater)); + /// ``` /// + /// For floating-point numbers, NaN does not have a total order and will result + /// in `None` when compared: + /// + /// ``` /// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None); /// ``` + /// + /// The results are determined by the order of evaluation. + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!([1.0, f64::NAN].iter().partial_cmp([2.0, f64::NAN].iter()), Some(Ordering::Less)); + /// assert_eq!([2.0, f64::NAN].iter().partial_cmp([1.0, f64::NAN].iter()), Some(Ordering::Greater)); + /// assert_eq!([f64::NAN, 1.0].iter().partial_cmp([f64::NAN, 2.0].iter()), None); + /// ``` + /// #[stable(feature = "iter_order", since = "1.5.0")] fn partial_cmp(self, other: I) -> Option where diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1675ed158c9..ff7821fb9ff 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -58,9 +58,10 @@ fn args(builder: &Builder<'_>) -> Vec { clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v))); clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v))); args.extend(clippy_lint_levels); + args.extend(builder.config.free_args.clone()); args } else { - vec![] + builder.config.free_args.clone() } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index e5fad538969..cd027a4abb7 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -97,6 +97,10 @@ pub struct Config { pub cmd: Subcommand, pub incremental: bool, pub dry_run: DryRun, + /// Arguments appearing after `--` to be forwarded to tools, + /// e.g. `--fix-broken` or test arguments. + pub free_args: Vec, + /// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should. #[cfg(not(test))] download_rustc_commit: Option, @@ -866,6 +870,7 @@ impl Config { config.keep_stage = flags.keep_stage; config.keep_stage_std = flags.keep_stage_std; config.color = flags.color; + config.free_args = flags.free_args.clone().unwrap_or_default(); if let Some(value) = flags.deny_warnings { config.deny_warnings = value; } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index ff927ed561b..f07e710a9e6 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -80,6 +80,10 @@ pub struct Flags { pub llvm_profile_generate: bool, pub llvm_bolt_profile_generate: bool, pub llvm_bolt_profile_use: Option, + + /// Arguments appearing after `--` to be forwarded to tools, + /// e.g. `--fix-broken` or test arguments. + pub free_args: Option>, } #[derive(Debug)] @@ -157,6 +161,12 @@ impl Default for Subcommand { impl Flags { pub fn parse(args: &[String]) -> Flags { + let (args, free_args) = if let Some(pos) = args.iter().position(|s| s == "--") { + let (args, free) = args.split_at(pos); + (args, Some(free[1..].to_vec())) + } else { + (args, None) + }; let mut subcommand_help = String::from( "\ Usage: x.py [options] [...] @@ -709,6 +719,7 @@ Arguments: llvm_profile_generate: matches.opt_present("llvm-profile-generate"), llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"), llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"), + free_args, } } } diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index e0280854541..e14440f57a8 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -183,6 +183,7 @@ impl Step for Miri { // Forward arguments. miri.arg("--").arg("--target").arg(target.rustc_target_arg()); miri.args(builder.config.cmd.args()); + miri.args(&builder.config.free_args); // miri tests need to know about the stage sysroot miri.env("MIRI_SYSROOT", &miri_sysroot); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index f8835fe11a8..9cd6107b43a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1588,6 +1588,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the .collect(); test_args.append(&mut builder.config.cmd.test_args()); + test_args.extend(builder.config.free_args.iter().map(|s| s.as_str())); // On Windows, replace forward slashes in test-args by backslashes // so the correct filters are passed to libtest diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 54c8f156f9d..10af968e34f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,7 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; -use rustc_middle::middle::resolve_lifetime as rl; +use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::fold::ir::TypeFolder; use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::TypeVisitable; @@ -200,11 +200,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( } fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime { - let def = cx.tcx.named_region(lifetime.hir_id); + let def = cx.tcx.named_bound_var(lifetime.hir_id); if let Some( - rl::Region::EarlyBound(node_id) - | rl::Region::LateBound(_, _, node_id) - | rl::Region::Free(_, node_id), + rbv::ResolvedArg::EarlyBound(node_id) + | rbv::ResolvedArg::LateBound(_, _, node_id) + | rbv::ResolvedArg::Free(_, node_id), ) = def { if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 4d8ce54dc5c..6fe665d7e40 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -129,7 +129,7 @@ fn external_generic_args<'tcx>( }); GenericArgs::Parenthesized { inputs, output } } else { - GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() } + GenericArgs::AngleBracketed { args: args.into(), bindings } } } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index d88409c356e..fc550936165 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -505,13 +505,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio if let FnRetTy::Return(ty) = sig.decl.output && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty) { - let out_region = cx.tcx.named_region(out.hir_id); + let out_region = cx.tcx.named_bound_var(out.hir_id); let args: Option> = sig .decl .inputs .iter() .filter_map(get_ref_lm) - .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region) + .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region) .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span)) .collect(); if let Some(args) = args diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index ef3abb9514f..409f7563184 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,7 +10,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 940; -const ISSUES_ENTRY_LIMIT: usize = 2001; +const ISSUES_ENTRY_LIMIT: usize = 1978; fn check_entries(path: &Path, bad: &mut bool) { for dir in Walk::new(&path.join("ui")) { diff --git a/tests/ui/issues/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs similarity index 100% rename from tests/ui/issues/issue-38821.rs rename to tests/ui/associated-types/issue-38821.rs diff --git a/tests/ui/issues/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr similarity index 100% rename from tests/ui/issues/issue-38821.stderr rename to tests/ui/associated-types/issue-38821.stderr diff --git a/tests/ui/issues/issue-83924.fixed b/tests/ui/borrowck/issue-83924.fixed similarity index 100% rename from tests/ui/issues/issue-83924.fixed rename to tests/ui/borrowck/issue-83924.fixed diff --git a/tests/ui/issues/issue-83924.rs b/tests/ui/borrowck/issue-83924.rs similarity index 100% rename from tests/ui/issues/issue-83924.rs rename to tests/ui/borrowck/issue-83924.rs diff --git a/tests/ui/issues/issue-83924.stderr b/tests/ui/borrowck/issue-83924.stderr similarity index 100% rename from tests/ui/issues/issue-83924.stderr rename to tests/ui/borrowck/issue-83924.stderr diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr index a0395ed4904..a3427e21cde 100644 --- a/tests/ui/bounds-lifetime.stderr +++ b/tests/ui/bounds-lifetime.stderr @@ -16,17 +16,24 @@ error: lifetime bounds cannot be used in this context LL | type C = for<'b, 'a: 'b +> fn(); | ^^ -error: only lifetime parameters can be used in this context +error[E0658]: only lifetime parameters can be used in this context --> $DIR/bounds-lifetime.rs:4:18 | LL | type D = for<'a, T> fn(); | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable -error: only lifetime parameters can be used in this context +error[E0658]: only lifetime parameters can be used in this context --> $DIR/bounds-lifetime.rs:5:18 | LL | type E = dyn for Fn(); | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr index 3c3b43d8cf3..9f4deaa774d 100644 --- a/tests/ui/closures/binder/disallow-const.stderr +++ b/tests/ui/closures/binder/disallow-const.stderr @@ -1,8 +1,12 @@ -error: only lifetime parameters can be used in this context +error[E0658]: only lifetime parameters can be used in this context --> $DIR/disallow-const.rs:4:15 | LL | for || -> () {}; | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr index 51b6773edea..22882ca2ba6 100644 --- a/tests/ui/closures/binder/disallow-ty.stderr +++ b/tests/ui/closures/binder/disallow-ty.stderr @@ -1,8 +1,12 @@ -error: only lifetime parameters can be used in this context +error[E0658]: only lifetime parameters can be used in this context --> $DIR/disallow-ty.rs:4:9 | LL | for || -> () {}; | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr index 4d6560e96e5..69b0f741156 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.stderr +++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr @@ -1,21 +1,3 @@ -error: only lifetime parameters can be used in this context - --> $DIR/cfg-generic-params.rs:7:45 - | -LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); - | ^ - -error: only lifetime parameters can be used in this context - --> $DIR/cfg-generic-params.rs:11:51 - | -LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; - | ^ - -error: only lifetime parameters can be used in this context - --> $DIR/cfg-generic-params.rs:15:54 - | -LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; - | ^ - error: cannot find attribute `unknown` in this scope --> $DIR/cfg-generic-params.rs:19:29 | @@ -46,5 +28,33 @@ error: cannot find attribute `unknown` in this scope LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; | ^^^^^^^ +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:7:45 + | +LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); + | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:11:51 + | +LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; + | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:15:54 + | +LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; + | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-33903.rs b/tests/ui/consts/issue-33903.rs similarity index 100% rename from tests/ui/issues/issue-33903.rs rename to tests/ui/consts/issue-33903.rs diff --git a/tests/ui/issues/issue-54582.rs b/tests/ui/consts/issue-54582.rs similarity index 100% rename from tests/ui/issues/issue-54582.rs rename to tests/ui/consts/issue-54582.rs diff --git a/tests/ui/issues/issue-2735-2.rs b/tests/ui/drop/issue-2735-2.rs similarity index 100% rename from tests/ui/issues/issue-2735-2.rs rename to tests/ui/drop/issue-2735-2.rs diff --git a/tests/ui/issues/issue-2735-3.rs b/tests/ui/drop/issue-2735-3.rs similarity index 100% rename from tests/ui/issues/issue-2735-3.rs rename to tests/ui/drop/issue-2735-3.rs diff --git a/tests/ui/issues/issue-2735.rs b/tests/ui/drop/issue-2735.rs similarity index 100% rename from tests/ui/issues/issue-2735.rs rename to tests/ui/drop/issue-2735.rs diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs new file mode 100644 index 00000000000..221e9133fcc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs @@ -0,0 +1,4 @@ +fn foo() where for T:, {} +//~^ ERROR only lifetime parameters can be used in this context + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr new file mode 100644 index 00000000000..75645e32401 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr @@ -0,0 +1,12 @@ +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/feature-gate-non_lifetime_binders.rs:1:20 + | +LL | fn foo() where for T:, {} + | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-75307.rs b/tests/ui/fmt/issue-75307.rs similarity index 100% rename from tests/ui/issues/issue-75307.rs rename to tests/ui/fmt/issue-75307.rs diff --git a/tests/ui/issues/issue-75307.stderr b/tests/ui/fmt/issue-75307.stderr similarity index 100% rename from tests/ui/issues/issue-75307.stderr rename to tests/ui/fmt/issue-75307.stderr diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr index f31aa554634..d605c9e0df7 100644 --- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr +++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr @@ -1,14 +1,21 @@ -error: only lifetime parameters can be used in this context +error[E0658]: only lifetime parameters can be used in this context --> $DIR/hrtb-wrong-kind.rs:1:18 | LL | fn a() where for T: Copy {} | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable -error: only lifetime parameters can be used in this context +error[E0658]: only lifetime parameters can be used in this context --> $DIR/hrtb-wrong-kind.rs:4:24 | LL | fn b() where for [(); C]: Copy {} | ^ + | + = note: see issue #1 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-39292.rs b/tests/ui/higher-rank-trait-bounds/issue-39292.rs similarity index 100% rename from tests/ui/issues/issue-39292.rs rename to tests/ui/higher-rank-trait-bounds/issue-39292.rs diff --git a/tests/ui/issues/issue-50576.rs b/tests/ui/loops/issue-50576.rs similarity index 100% rename from tests/ui/issues/issue-50576.rs rename to tests/ui/loops/issue-50576.rs diff --git a/tests/ui/issues/issue-50576.stderr b/tests/ui/loops/issue-50576.stderr similarity index 100% rename from tests/ui/issues/issue-50576.stderr rename to tests/ui/loops/issue-50576.stderr diff --git a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs similarity index 100% rename from tests/ui/issues/issue-22536-copy-mustnt-zero.rs rename to tests/ui/moves/issue-22536-copy-mustnt-zero.rs diff --git a/tests/ui/issues/issue-27583.rs b/tests/ui/nll/issue-27583.rs similarity index 100% rename from tests/ui/issues/issue-27583.rs rename to tests/ui/nll/issue-27583.rs diff --git a/tests/ui/issues/issue-48179.rs b/tests/ui/nll/issue-48179.rs similarity index 100% rename from tests/ui/issues/issue-48179.rs rename to tests/ui/nll/issue-48179.rs diff --git a/tests/ui/issues/issue-75777.rs b/tests/ui/nll/issue-75777.rs similarity index 100% rename from tests/ui/issues/issue-75777.rs rename to tests/ui/nll/issue-75777.rs diff --git a/tests/ui/issues/issue-75777.stderr b/tests/ui/nll/issue-75777.stderr similarity index 100% rename from tests/ui/issues/issue-75777.stderr rename to tests/ui/nll/issue-75777.stderr diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover-fn-ptr-with-generics.stderr index 1da9c18571b..069fcffe9a0 100644 --- a/tests/ui/parser/recover-fn-ptr-with-generics.stderr +++ b/tests/ui/parser/recover-fn-ptr-with-generics.stderr @@ -88,12 +88,6 @@ error: expected identifier, found `>` LL | type QuiteBroken = fn(); | ^ expected identifier -error: lifetime bounds cannot be used in this context - --> $DIR/recover-fn-ptr-with-generics.rs:22:26 - | -LL | let _: extern fn<'a: 'static>(); - | ^^^^^^^ - error[E0412]: cannot find type `T` in this scope --> $DIR/recover-fn-ptr-with-generics.rs:5:27 | @@ -106,6 +100,12 @@ error[E0412]: cannot find type `T` in this scope LL | type Identity = fn(T) -> T; | ^ not found in this scope +error: lifetime bounds cannot be used in this context + --> $DIR/recover-fn-ptr-with-generics.rs:22:26 + | +LL | let _: extern fn<'a: 'static>(); + | ^^^^^^^ + error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-40003.rs b/tests/ui/recursion_limit/issue-40003.rs similarity index 100% rename from tests/ui/issues/issue-40003.rs rename to tests/ui/recursion_limit/issue-40003.rs diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs new file mode 100644 index 00000000000..0b1f9ab57c9 --- /dev/null +++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs @@ -0,0 +1,15 @@ +// Regression test for #108132: do not ICE upon unmet trait alias constraint in generic impl + +#![feature(trait_alias)] + +trait IteratorAlias = Iterator; + +struct Foo(I); + +impl Foo { + fn f() {} +} + +fn main() { + Foo::<()>::f() //~ trait bounds were not satisfied +} diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr new file mode 100644 index 00000000000..f1b259d5a65 --- /dev/null +++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr @@ -0,0 +1,25 @@ +error[E0599]: the function or associated item `f` exists for struct `Foo<()>`, but its trait bounds were not satisfied + --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:14:16 + | +LL | struct Foo(I); + | ------------- function or associated item `f` not found for this struct +... +LL | Foo::<()>::f() + | ^ function or associated item cannot be called on `Foo<()>` due to unsatisfied trait bounds + | +note: trait bound `(): Iterator` was not satisfied + --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:5:23 + | +LL | trait IteratorAlias = Iterator; + | ------------- ^^^^^^^^ unsatisfied trait bound introduced here +note: trait bound `(): IteratorAlias` was not satisfied + --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9 + | +LL | impl Foo { + | ^^^^^^^^^^^^^ ------ + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs new file mode 100644 index 00000000000..a797aae65db --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/basic.rs @@ -0,0 +1,19 @@ +// check-pass +// Basic test that show's we can succesfully typeck a `for` where clause. + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Trait {} + +impl Trait for T {} + +fn foo() +where + for T: Trait, +{ +} + +fn main() { + foo(); +} diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr new file mode 100644 index 00000000000..fddc5d9fc25 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/basic.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/basic.rs:4:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs new file mode 100644 index 00000000000..460f68907e8 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/fail.rs @@ -0,0 +1,23 @@ +// Error reporting for where `for T: Trait` doesn't hold + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Trait {} + +fn fail() +where + for T: Trait, +{} + +fn auto_trait() +where + for T: Send, +{} + +fn main() { + fail(); + //~^ ERROR the trait bound `T: Trait` is not satisfied + auto_trait(); + //~^ ERROR `T` cannot be sent between threads safely +} diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr new file mode 100644 index 00000000000..ba5953193a4 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -0,0 +1,43 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/fail.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/fail.rs:19:5 + | +LL | fail(); + | ^^^^ the trait `Trait` is not implemented for `T` + | +note: required by a bound in `fail` + --> $DIR/fail.rs:10:15 + | +LL | fn fail() + | ---- required by a bound in this +LL | where +LL | for T: Trait, + | ^^^^^ required by this bound in `fail` + +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/fail.rs:21:5 + | +LL | auto_trait(); + | ^^^^^^^^^^ `T` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `T` +note: required by a bound in `auto_trait` + --> $DIR/fail.rs:15:15 + | +LL | fn auto_trait() + | ---------- required by a bound in this +LL | where +LL | for T: Send, + | ^^^^ required by this bound in `auto_trait` + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs new file mode 100644 index 00000000000..8fb7dd27605 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs @@ -0,0 +1,13 @@ +// Tests to make sure that we reject polymorphic dyn trait. + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Test {} + +fn foo() -> &'static dyn for Test { + //~^ ERROR late-bound type parameter not allowed on trait object types + todo!() +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr new file mode 100644 index 00000000000..44071107de4 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/on-dyn.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on trait object types + --> $DIR/on-dyn.rs:8:30 + | +LL | fn foo() -> &'static dyn for Test { + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs new file mode 100644 index 00000000000..0aaff52b6d8 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs @@ -0,0 +1,13 @@ +// Tests to make sure that we reject polymorphic fn ptrs. + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +fn foo() -> for fn(T) { + //~^ ERROR late-bound type parameter not allowed on function pointer types + todo!() +} + +fn main() { + foo()(1i32); +} diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr new file mode 100644 index 00000000000..bb7dccaf07d --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/on-ptr.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on function pointer types + --> $DIR/on-ptr.rs:6:17 + | +LL | fn foo() -> for fn(T) { + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/issues/issue-53712.rs b/tests/ui/typeck/issue-53712.rs similarity index 100% rename from tests/ui/issues/issue-53712.rs rename to tests/ui/typeck/issue-53712.rs diff --git a/tests/ui/issues/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr similarity index 100% rename from tests/ui/issues/issue-53712.stderr rename to tests/ui/typeck/issue-53712.stderr diff --git a/tests/ui/issues/issue-7813.rs b/tests/ui/typeck/issue-7813.rs similarity index 100% rename from tests/ui/issues/issue-7813.rs rename to tests/ui/typeck/issue-7813.rs diff --git a/tests/ui/issues/issue-7813.stderr b/tests/ui/typeck/issue-7813.stderr similarity index 100% rename from tests/ui/issues/issue-7813.stderr rename to tests/ui/typeck/issue-7813.stderr