Auto merge of #108145 - matthiaskrgr:rollup-bgadak1, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #104068 (rustdoc: Add PartialOrd trait to doc comment explanation)
 - #107489 (Implement partial support for non-lifetime binders)
 - #107905 (Pass arguments to `x` subcommands with `--`)
 - #108009 (Move some tests)
 - #108086 (wasm: Register the `relaxed-simd` target feature)
 - #108104 (don't into self)
 - #108133 (Small cleanups around `EarlyBinder`)
 - #108136 (Do not ICE on unmet trait alias impl bounds)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-02-17 01:14:39 +00:00
commit ea218392a4
95 changed files with 822 additions and 370 deletions

View File

@ -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) { fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
self.check_decl_num_args(fn_decl); self.check_decl_num_args(fn_decl);
self.check_decl_cvaradic_pos(fn_decl); self.check_decl_cvaradic_pos(fn_decl);
@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> {
) )
.emit(); .emit();
}); });
self.check_late_bound_lifetime_defs(&bfty.generic_params);
if let Extern::Implicit(_) = bfty.ext { if let Extern::Implicit(_) = bfty.ext {
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo()); let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
self.maybe_lint_missing_abi(sig_span, ty.id); 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 { for predicate in &generics.where_clause.predicates {
match predicate { match predicate {
WherePredicate::BoundPredicate(bound_pred) => { 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 // 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, // binder and thus we only allow a single level of quantification. However,
// the syntax of Rust permits quantification in two places in where clauses, // 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) 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) { fn visit_variant_data(&mut self, s: &'a VariantData) {
self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s)) 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(); .emit();
} }
if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
self.check_late_bound_lifetime_defs(generic_params);
}
if let FnKind::Fn( if let FnKind::Fn(
_, _,
_, _,

View File

@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use crate::errors::ForbiddenLifetimeBound;
macro_rules! gate_feature_fn { macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{ ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
let (visitor, has_feature, span, name, explain, help) = let (visitor, has_feature, span, name, explain, help) =
@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
} }
ImplTraitVisitor { vis: self }.visit_ty(ty); 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> { impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
.. ..
}) = attr_info }) = 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. // Check unstable flavors of the `#[doc]` attribute.
if attr.has_name(sym::doc) { if attr.has_name(sym::doc) {
@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::BareFn(bare_fn_ty) => { ast::TyKind::BareFn(bare_fn_ty) => {
// Function pointers cannot be `const` // Function pointers cannot be `const`
self.check_extern(bare_fn_ty.ext, ast::Const::No); self.check_extern(bare_fn_ty.ext, ast::Const::No);
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
} }
ast::TyKind::Never => { ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental"); 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) 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) { fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
if let ast::FnRetTy::Ty(output_ty) = ret_ty { if let ast::FnRetTy::Ty(output_ty) = ret_ty {
if let ast::TyKind::Never = output_ty.kind { if let ast::TyKind::Never = output_ty.kind {
@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_pat(self, pattern) 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) { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let Some(header) = fn_kind.header() { if let Some(header) = fn_kind.header() {
// Stability of const fn methods are covered in `visit_assoc_item` below. // Stability of const fn methods are covered in `visit_assoc_item` below.
self.check_extern(header.ext, header.constness); 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() { if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
} }

View File

@ -731,7 +731,7 @@ pub fn eval_condition(
sess, sess,
sym::cfg_target_compact, sym::cfg_target_compact,
cfg.span, cfg.span,
&"compact `cfg(target(..))` is experimental and subject to change" "compact `cfg(target(..))` is experimental and subject to change"
).emit(); ).emit();
} }

View File

@ -286,6 +286,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("mutable-globals", Some(sym::wasm_target_feature)), ("mutable-globals", Some(sym::wasm_target_feature)),
("nontrapping-fptoint", Some(sym::wasm_target_feature)), ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
("reference-types", 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)), ("sign-ext", Some(sym::wasm_target_feature)),
("simd128", None), ("simd128", None),
// tidy-alphabetical-end // tidy-alphabetical-end

View File

@ -473,6 +473,8 @@ declare_features! (
(active, no_sanitize, "1.42.0", Some(39699), None), (active, no_sanitize, "1.42.0", Some(39699), None),
/// Allows using the `non_exhaustive_omitted_patterns` lint. /// Allows using the `non_exhaustive_omitted_patterns` lint.
(active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
/// Allows `for<T>` 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. /// 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 /// 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. /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.

View File

@ -14,7 +14,7 @@ use crate::errors::{
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, 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 crate::require_c_abi_if_c_variadic;
use rustc_ast::TraitObjectSyntax; use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@ -225,10 +225,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let tcx = self.tcx(); let tcx = self.tcx();
let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id)); 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) { match tcx.named_bound_var(lifetime.hir_id) {
Some(rl::Region::Static) => tcx.lifetimes.re_static, 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 name = lifetime_name(def_id.expect_local());
let br = ty::BoundRegion { let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index), var: ty::BoundVar::from_u32(index),
@ -237,7 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.mk_re_late_bound(debruijn, br) 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 name = tcx.hir().ty_param_name(def_id.expect_local());
let item_def_id = tcx.hir().ty_param_owner(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); 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 }) 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()); let name = lifetime_name(id.expect_local());
tcx.mk_re_free(scope, ty::BrNamed(id, name)) 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) self.ast_region_to_region(lifetime, None)
} else { } else {
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_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) self.ast_region_to_region(lifetime, None)
} else { } else {
self.re_infer(None, span).unwrap_or_else(|| { self.re_infer(None, span).unwrap_or_else(|| {
@ -2600,6 +2600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self, &self,
opt_self_ty: Option<Ty<'tcx>>, opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path<'_>, path: &hir::Path<'_>,
hir_id: hir::HirId,
permit_variants: bool, permit_variants: bool,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
@ -2663,11 +2664,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
}); });
let def_id = def_id.expect_local(); match tcx.named_bound_var(hir_id) {
let item_def_id = tcx.hir().ty_param_owner(def_id); Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
let generics = tcx.generics_of(item_def_id); let name =
let index = generics.param_def_id_to_index[&def_id.to_def_id()]; tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) 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 { .. } => { Res::SelfTyParam { .. } => {
// `Self` in trait or type alias. // `Self` in trait or type alias.
@ -2870,14 +2885,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
hir::TyKind::BareFn(bf) => { hir::TyKind::BareFn(bf) => {
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); 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, ast_ty.hir_id,
bf.unsafety, bf.unsafety,
bf.abi, bf.abi,
bf.decl, bf.decl,
None, None,
Some(ast_ty), 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) => { hir::TyKind::TraitObject(bounds, lifetime, repr) => {
self.maybe_lint_bare_trait(ast_ty, in_path); 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::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar, 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)) => { hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path); debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); 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) => { &hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id); 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<ErrorGuaranteed> {
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() })
})
}

View File

@ -41,8 +41,8 @@ use std::iter;
mod generics_of; mod generics_of;
mod item_bounds; mod item_bounds;
mod lifetimes;
mod predicates_of; mod predicates_of;
mod resolve_bound_vars;
mod type_of; mod type_of;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
} }
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
lifetimes::provide(providers); resolve_bound_vars::provide(providers);
*providers = Providers { *providers = Providers {
opt_const_param_of: type_of::opt_const_param_of, opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of, type_of: type_of::type_of,

View File

@ -1,4 +1,4 @@
use crate::middle::resolve_lifetime as rl; use crate::middle::resolve_bound_vars as rbv;
use hir::{ use hir::{
intravisit::{self, Visitor}, intravisit::{self, Visitor},
GenericParamKind, HirId, Node, GenericParamKind, HirId, Node,
@ -394,10 +394,11 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
return; return;
} }
match self.tcx.named_region(lt.hir_id) { match self.tcx.named_bound_var(lt.hir_id) {
Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {} Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {}
Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {} Some(rbv::ResolvedArg::LateBound(debruijn, _, _))
Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => { if debruijn < self.outer_index => {}
Some(rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..)) | None => {
self.has_late_bound_regions = Some(lt.ident.span); self.has_late_bound_regions = Some(lt.ident.span);
} }
} }

View File

@ -16,7 +16,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::hir::nested_filter; 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_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
@ -24,59 +24,61 @@ use rustc_span::Span;
use std::fmt; use std::fmt;
trait RegionExt { 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<DefId>; fn id(&self) -> Option<DefId>;
fn shifted(self, amount: u32) -> Region; fn shifted(self, amount: u32) -> ResolvedArg;
} }
impl RegionExt for Region { impl RegionExt for ResolvedArg {
fn early(param: &GenericParam<'_>) -> (LocalDefId, Region) { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
debug!("Region::early: def_id={:?}", param.def_id); debug!("ResolvedArg::early: def_id={:?}", param.def_id);
(param.def_id, Region::EarlyBound(param.def_id.to_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; let depth = ty::INNERMOST;
debug!( debug!(
"Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}", "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
idx, param, depth, param.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<DefId> { fn id(&self) -> Option<DefId> {
match *self { 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 { match self {
Region::LateBound(debruijn, idx, id) => { ResolvedArg::LateBound(debruijn, idx, id) => {
Region::LateBound(debruijn.shifted_in(amount), idx, id) ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
} }
_ => self, _ => 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. /// 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 /// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly. /// is silly.
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct NamedRegionMap { struct NamedVarMap {
// maps from every use of a named (not anonymous) lifetime to a // maps from every use of a named (not anonymous) bound var to a
// `Region` describing how that region is bound // `ResolvedArg` describing how that variable is bound
defs: HirIdMap<Region>, defs: HirIdMap<ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include: // Maps relevant hir items to the bound vars on them. These include:
// - function defs // - function defs
@ -87,9 +89,9 @@ struct NamedRegionMap {
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>, late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
} }
struct LifetimeContext<'a, 'tcx> { struct BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
map: &'a mut NamedRegionMap, map: &'a mut NamedVarMap,
scope: ScopeRef<'a>, scope: ScopeRef<'a>,
} }
@ -102,7 +104,7 @@ enum Scope<'a> {
Binder { Binder {
/// We use an IndexMap here because we want these lifetimes in order /// We use an IndexMap here because we want these lifetimes in order
/// for diagnostics. /// for diagnostics.
lifetimes: FxIndexMap<LocalDefId, Region>, bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
scope_type: BinderScopeType, scope_type: BinderScopeType,
@ -141,7 +143,7 @@ enum Scope<'a> {
/// inferred in a function body or potentially error outside one), /// inferred in a function body or potentially error outside one),
/// for the default choice of lifetime in a trait object type. /// for the default choice of lifetime in a trait object type.
ObjectLifetimeDefault { ObjectLifetimeDefault {
lifetime: Option<Region>, lifetime: Option<ResolvedArg>,
s: ScopeRef<'a>, s: ScopeRef<'a>,
}, },
@ -150,7 +152,7 @@ enum Scope<'a> {
/// lifetimes encountered when identifying the trait that an associated type /// lifetimes encountered when identifying the trait that an associated type
/// is declared on. /// is declared on.
Supertrait { Supertrait {
lifetimes: Vec<ty::BoundVariableKind>, bound_vars: Vec<ty::BoundVariableKind>,
s: ScopeRef<'a>, s: ScopeRef<'a>,
}, },
@ -185,9 +187,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 { 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") .debug_struct("Binder")
.field("lifetimes", lifetimes) .field("bound_vars", bound_vars)
.field("scope_type", scope_type) .field("scope_type", scope_type)
.field("hir_id", hir_id) .field("hir_id", hir_id)
.field("where_bound_origin", where_bound_origin) .field("where_bound_origin", where_bound_origin)
@ -202,9 +204,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
.field("lifetime", lifetime) .field("lifetime", lifetime)
.field("s", &"..") .field("s", &"..")
.finish(), .finish(),
Scope::Supertrait { lifetimes, s: _ } => f Scope::Supertrait { bound_vars, s: _ } => f
.debug_struct("Supertrait") .debug_struct("Supertrait")
.field("lifetimes", lifetimes) .field("bound_vars", bound_vars)
.field("s", &"..") .field("s", &"..")
.finish(), .finish(),
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").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) { pub(crate) fn provide(providers: &mut ty::query::Providers) {
*providers = 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, is_late_bound_map,
object_lifetime_default, 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 ..*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 /// 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))] #[instrument(level = "debug", skip(tcx))]
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes { fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
let mut named_region_map = let mut named_variable_map =
NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() }; NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
let mut visitor = LifetimeContext { let mut visitor = BoundVarContext {
tcx, tcx,
map: &mut named_region_map, map: &mut named_variable_map,
scope: &Scope::Root { opt_parent_item: None }, scope: &Scope::Root { opt_parent_item: None },
}; };
match tcx.hir().owner(local_def_id) { 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(_) => {} 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(); let map = rl.defs.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v); 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(); let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v); map.insert(hir_id.local_id, v);
} }
@ -276,21 +278,33 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
rl rl
} }
fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind { fn late_arg_as_bound_arg<'tcx>(
match region { tcx: TyCtxt<'tcx>,
Region::LateBound(_, _, def_id) => { 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())); 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. /// 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<ty::BoundVariableKind>, BinderScopeType) { fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
let mut scope = self.scope; let mut scope = self.scope;
let mut supertrait_lifetimes = vec![]; let mut supertrait_bound_vars = vec![];
loop { loop {
match scope { match scope {
Scope::Body { .. } | Scope::Root { .. } => { Scope::Body { .. } | Scope::Root { .. } => {
@ -301,14 +315,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
scope = s; scope = s;
} }
Scope::Supertrait { s, lifetimes } => { Scope::Supertrait { s, bound_vars } => {
supertrait_lifetimes = lifetimes.clone(); supertrait_bound_vars = bound_vars.clone();
scope = s; scope = s;
} }
Scope::TraitRefBoundary { .. } => { Scope::TraitRefBoundary { .. } => {
// We should only see super trait lifetimes if there is a `Binder` above // 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); break (vec![], BinderScopeType::Normal);
} }
@ -316,14 +330,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// Nested poly trait refs have the binders concatenated // Nested poly trait refs have the binders concatenated
let mut full_binders = let mut full_binders =
self.map.late_bound_vars.entry(*hir_id).or_default().clone(); 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); 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; type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map { 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<LocalDefId, Region>, Vec<_>) = let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params bound_generic_params
.iter() .iter()
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate() .enumerate()
.map(|(late_bound_idx, param)| { .map(|(late_bound_idx, param)| {
let pair = Region::late(late_bound_idx as u32, param); let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_region_as_bound_region(self.tcx, &pair.1); let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r) (pair, r)
}) })
.unzip(); .unzip();
@ -401,7 +414,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.record_late_bound_vars(e.hir_id, binders); self.record_late_bound_vars(e.hir_id, binders);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: e.hir_id, hir_id: e.hir_id,
lifetimes, bound_vars,
s: self.scope, s: self.scope,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
where_bound_origin: None, 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 // conservatively add all resolved lifetimes. Otherwise we run into problems in
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`. // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
let parent_item = self.tcx.hir().get_parent_item(item.hir_id()); 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* // We need to add *all* deps, since opaque tys may want them from *us*
for (&owner, defs) in resolved_lifetimes.defs.iter() { for (&owner, defs) in resolved_lifetimes.defs.iter() {
defs.iter().for_each(|(&local_id, region)| { 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 { hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_), origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
generics, generics,
.. ..
}) => { }) => {
// We want to start our early-bound indices at the end of the parent scope, // We want to start our early-bound indices at the end of the parent scope,
// not including any parent `impl Trait`s. // not including any parent `impl Trait`s.
let mut lifetimes = FxIndexMap::default(); let mut bound_vars = FxIndexMap::default();
debug!(?generics.params); debug!(?generics.params);
for param in generics.params { for param in generics.params {
match param.kind { let (def_id, reg) = ResolvedArg::early(&param);
GenericParamKind::Lifetime { .. } => { bound_vars.insert(def_id, reg);
let (def_id, reg) = Region::early(&param);
lifetimes.insert(def_id, reg);
}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
}
} }
let scope = Scope::Binder { let scope = Scope::Root { opt_parent_item: Some(parent) };
hir_id: item.hir_id(),
lifetimes,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, |this| { self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope }; let scope = Scope::Binder {
this.with(scope, |this| intravisit::walk_item(this, item)) 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::TyAlias(_, generics)
| hir::ItemKind::Enum(_, generics) | hir::ItemKind::Enum(_, generics)
@ -516,18 +528,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(generics, ..) | hir::ItemKind::TraitAlias(generics, ..)
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => { | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters. // These kinds of items have only early-bound lifetime parameters.
let lifetimes = generics let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
self.record_late_bound_vars(item.hir_id(), vec![]); self.record_late_bound_vars(item.hir_id(), vec![]);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: item.hir_id(), hir_id: item.hir_id(),
lifetimes, bound_vars,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
s: self.scope, s: self.scope,
where_bound_origin: None, 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>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
match ty.kind { match ty.kind {
hir::TyKind::BareFn(c) => { hir::TyKind::BareFn(c) => {
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
.generic_params .generic_params
.iter() .iter()
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate() .enumerate()
.map(|(late_bound_idx, param)| { .map(|(late_bound_idx, param)| {
let pair = Region::late(late_bound_idx as u32, param); let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_region_as_bound_region(self.tcx, &pair.1); let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r) (pair, r)
}) })
.unzip(); .unzip();
self.record_late_bound_vars(ty.hir_id, binders); self.record_late_bound_vars(ty.hir_id, binders);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: ty.hir_id, hir_id: ty.hir_id,
lifetimes, bound_vars,
s: self.scope, s: self.scope,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
where_bound_origin: None, 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. // well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed. // In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned(); 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 continue
}; };
let Some(def_id) = def_id.as_local() else { 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) => { Type(bounds, ty) => {
let generics = &trait_item.generics; let generics = &trait_item.generics;
let lifetimes = generics let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
self.record_late_bound_vars(trait_item.hir_id(), vec![]); self.record_late_bound_vars(trait_item.hir_id(), vec![]);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: trait_item.hir_id(), hir_id: trait_item.hir_id(),
lifetimes, bound_vars,
s: self.scope, s: self.scope,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
where_bound_origin: None, where_bound_origin: None,
@ -768,18 +765,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}), }),
Type(ty) => { Type(ty) => {
let generics = &impl_item.generics; let generics = &impl_item.generics;
let lifetimes: FxIndexMap<LocalDefId, Region> = generics let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
.params generics.params.iter().map(ResolvedArg::early).collect();
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
})
.collect();
self.record_late_bound_vars(impl_item.hir_id(), vec![]); self.record_late_bound_vars(impl_item.hir_id(), vec![]);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: impl_item.hir_id(), hir_id: impl_item.hir_id(),
lifetimes, bound_vars,
s: self.scope, s: self.scope,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
where_bound_origin: None, where_bound_origin: None,
@ -803,7 +794,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.res { 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) => { hir::LifetimeName::Param(param_def_id) => {
self.resolve_lifetime_ref(param_def_id, lifetime_ref) 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() { for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1; let depth = path.segments.len() - i - 1;
if let Some(args) = segment.args { if let Some(args) = segment.args {
self.visit_segment_args(path.res, depth, 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( fn visit_fn(
@ -869,24 +865,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
origin, origin,
.. ..
}) => { }) => {
let lifetimes: FxIndexMap<LocalDefId, Region> =
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params bound_generic_params
.iter() .iter()
.filter(|param| { .enumerate()
matches!(param.kind, GenericParamKind::Lifetime { .. }) .map(|(late_bound_idx, param)| {
}) let pair = ResolvedArg::late(late_bound_idx as u32, param);
.enumerate() let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
.map(|(late_bound_idx, param)| { (pair, r)
Region::late(late_bound_idx as u32, param) })
}) .unzip();
.collect();
let binders: Vec<_> =
lifetimes
.iter()
.map(|(_, region)| {
late_region_as_bound_region(this.tcx, region)
})
.collect();
this.record_late_bound_vars(hir_id, binders.clone()); this.record_late_bound_vars(hir_id, binders.clone());
// Even if there are no lifetimes defined here, we still wrap it in a binder // 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 // 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. // being wrong.
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id, hir_id,
lifetimes, bound_vars,
s: this.scope, s: this.scope,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
where_bound_origin: Some(origin), where_bound_origin: Some(origin),
@ -920,7 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if lt.res != hir::LifetimeName::Static { if lt.res != hir::LifetimeName::Static {
continue; continue;
} }
this.insert_lifetime(lt, Region::Static); this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
this.tcx this.tcx
.sess .sess
.struct_span_warn( .struct_span_warn(
@ -964,7 +953,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.record_late_bound_vars(*hir_id, binders); self.record_late_bound_vars(*hir_id, binders);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: *hir_id, hir_id: *hir_id,
lifetimes: FxIndexMap::default(), bound_vars: FxIndexMap::default(),
s: self.scope, s: self.scope,
scope_type, scope_type,
where_bound_origin: None, 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 (mut binders, scope_type) = self.poly_trait_ref_binder_info();
let initial_bound_vars = binders.len() as u32; let initial_bound_vars = binders.len() as u32;
let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default(); let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
let binders_iter = trait_ref let binders_iter =
.bound_generic_params trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
.iter() let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
.enumerate() bound_vars.insert(pair.0, pair.1);
.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);
r r
}); });
binders.extend(binders_iter); binders.extend(binders_iter);
@ -1006,7 +991,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// refs. // refs.
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id: trait_ref.trait_ref.hir_ref_id, hir_id: trait_ref.trait_ref.hir_ref_id,
lifetimes, bound_vars,
s: self.scope, s: self.scope,
scope_type, scope_type,
where_bound_origin: None, 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<F>(&mut self, wrap_scope: Scope<'_>, f: F) fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
where where
F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>), F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{ {
let LifetimeContext { tcx, map, .. } = self; let BoundVarContext { tcx, map, .. } = self;
let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope }; let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
{ {
let _enter = span.enter(); let _enter = span.enter();
@ -1110,23 +1095,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
generics: &'tcx hir::Generics<'tcx>, generics: &'tcx hir::Generics<'tcx>,
walk: F, walk: F,
) where ) 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 mut named_late_bound_vars = 0;
let lifetimes: FxIndexMap<LocalDefId, Region> = generics let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
.params .params
.iter() .iter()
.filter_map(|param| match param.kind { .map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => { GenericParamKind::Lifetime { .. } => {
if self.tcx.is_late_bound(param.hir_id) { if self.tcx.is_late_bound(param.hir_id) {
let late_bound_idx = named_late_bound_vars; let late_bound_idx = named_late_bound_vars;
named_late_bound_vars += 1; named_late_bound_vars += 1;
Some(Region::late(late_bound_idx, param)) ResolvedArg::late(late_bound_idx, param)
} else { } else {
Some(Region::early(param)) ResolvedArg::early(param)
} }
} }
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
ResolvedArg::early(param)
}
}) })
.collect(); .collect();
@ -1139,14 +1126,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}) })
.enumerate() .enumerate()
.map(|(late_bound_idx, param)| { .map(|(late_bound_idx, param)| {
let pair = Region::late(late_bound_idx as u32, param); let pair = ResolvedArg::late(late_bound_idx as u32, param);
late_region_as_bound_region(self.tcx, &pair.1) late_arg_as_bound_arg(self.tcx, &pair.1, param)
}) })
.collect(); .collect();
self.record_late_bound_vars(hir_id, binders); self.record_late_bound_vars(hir_id, binders);
let scope = Scope::Binder { let scope = Scope::Binder {
hir_id, hir_id,
lifetimes, bound_vars,
s: self.scope, s: self.scope,
scope_type: BinderScopeType::Normal, scope_type: BinderScopeType::Normal,
where_bound_origin: None, where_bound_origin: None,
@ -1177,15 +1164,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Root { opt_parent_item } => { Scope::Root { opt_parent_item } => {
if let Some(parent_item) = opt_parent_item if let Some(parent_item) = opt_parent_item
&& let parent_generics = self.tcx.generics_of(parent_item) && let parent_generics = self.tcx.generics_of(parent_item)
&& parent_generics.param_def_id_to_index.contains_key(&region_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; break None;
} }
Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => { Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
if let Some(&def) = lifetimes.get(&region_def_id) { if let Some(&def) = bound_vars.get(&region_def_id) {
break Some(def.shifted(late_depth)); break Some(def.shifted(late_depth));
} }
match scope_type { match scope_type {
@ -1259,7 +1246,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}; };
if let Some(mut def) = result { 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. // Do not free early-bound regions, only late-bound ones.
} else if let Some(body_id) = outermost_body { } else if let Some(body_id) = outermost_body {
let fn_id = self.tcx.hir().body_owner(body_id); let fn_id = self.tcx.hir().body_owner(body_id);
@ -1275,10 +1262,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(..), 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), .. }) => { 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(&param_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))] #[instrument(level = "debug", skip(self))]
fn visit_segment_args( fn visit_segment_args(
&mut self, &mut self,
@ -1415,10 +1453,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if in_body { if in_body {
None None
} else { } else {
Some(Region::Static) Some(ResolvedArg::StaticLifetime)
} }
} }
ObjectLifetimeDefault::Static => Some(Region::Static), ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
ObjectLifetimeDefault::Param(param_def_id) => { ObjectLifetimeDefault::Param(param_def_id) => {
// This index can be used with `generic_args` since `parent_count == 0`. // This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize; let index = generics.param_def_id_to_index[&param_def_id] as usize;
@ -1507,18 +1545,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// in the trait ref `YY<...>` in `Item: YY<...>`. // in the trait ref `YY<...>` in `Item: YY<...>`.
for binding in generic_args.bindings { for binding in generic_args.bindings {
let scope = Scope::ObjectLifetimeDefault { 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, s: self.scope,
}; };
if let Some(type_def_id) = type_def_id { if let Some(type_def_id) = type_def_id {
let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes( let bound_vars =
self.tcx, BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
type_def_id,
binding.ident,
);
self.with(scope, |this| { self.with(scope, |this| {
let scope = Scope::Supertrait { let scope = Scope::Supertrait {
lifetimes: lifetimes.unwrap_or_default(), bound_vars: bound_vars.unwrap_or_default(),
s: this.scope, s: this.scope,
}; };
this.with(scope, |this| this.visit_assoc_type_binding(binding)); 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 /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
/// the starting trait `Bar`, we would return `Some(['b, 'a])`. /// the starting trait `Bar`, we would return `Some(['b, 'a])`.
fn supertrait_hrtb_lifetimes( fn supertrait_hrtb_vars(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
def_id: DefId, def_id: DefId,
assoc_name: Ident, assoc_name: Ident,
@ -1626,7 +1665,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
scope = s; scope = s;
} }
Scope::Root { .. } | Scope::Elision { .. } => break Region::Static, Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
@ -1641,7 +1680,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} }
#[instrument(level = "debug", skip(self))] #[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); debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id, def); 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 /// Sometimes we resolve a lifetime, but later find that it is an
/// error (esp. around impl trait). In that case, we remove the /// error (esp. around impl trait). In that case, we remove the
/// entry into `map.defs` so as not to confuse later code. /// 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); let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
assert_eq!(old_value, Some(bad_def)); assert_eq!(old_value, Some(bad_def));
} }

View File

@ -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. // 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 // 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. // 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( self.tcx.mk_trait_ref(
obligation.impl_def_id, obligation.impl_or_alias_def_id,
ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_def_id), ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
) )
} else { } else {
self.tcx 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()) .map(|impl_def| impl_def.skip_binder())
// It is possible that this is absent. In this case, we make no progress. // It is possible that this is absent. In this case, we make no progress.
.ok_or(expr)? .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_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
let impl_predicates: ty::GenericPredicates<'tcx> = 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 { let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
// We don't have the index, so we can only guess. // We don't have the index, so we can only guess.
return Err(expr); return Err(expr);

View File

@ -1740,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *qpath { match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => { QPath::Resolved(ref maybe_qself, ref path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw); 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)) (path.res, self.handle_raw_ty(path_span, ty))
} }
QPath::TypeRelative(ref qself, ref segment) => { QPath::TypeRelative(ref qself, ref segment) => {

View File

@ -1576,7 +1576,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
traits::ImplDerivedObligation(Box::new( traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause { traits::ImplDerivedObligationCause {
derived, derived,
impl_def_id, impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: None, impl_def_predicate_index: None,
span, span,
}, },

View File

@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ObligationCauseCode::ImplDerivedObligation(data) ObligationCauseCode::ImplDerivedObligation(data)
if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) => 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, _ => None,
}) })
@ -714,7 +714,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
} }
Some(Node::Item(hir::Item { Some(Node::Item(hir::Item {
ident, kind: hir::ItemKind::Trait(..), .. ident,
kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
..
})) => { })) => {
skip_list.insert(p); skip_list.insert(p);
let entry = spanned_predicates.entry(ident.span); let entry = spanned_predicates.entry(ident.span);

View File

@ -125,11 +125,11 @@ impl<'tcx> InferCtxt<'tcx> {
} }
(ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => { (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) Ok(b)
} }
(_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => { (_, 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) Ok(a)
} }

View File

@ -2,7 +2,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter; 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}; use rustc_middle::ty::{self, Region, TyCtxt};
/// This function calls the `visit_ty` method for the parameters /// 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, _) => { hir::TyKind::Ref(ref lifetime, _) => {
// the lifetime of the Ref // the lifetime of the Ref
let hir_id = lifetime.hir_id; 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 // Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound // error. We will then search the function parameters for a bound
// region at the right depth with the same index // 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); debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id { if id == def_id {
self.found_type = Some(arg); 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 // error. We will then search the function parameters for a bound
// region at the right depth with the same index // 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, _), ty::BrNamed(def_id, _),
) => { ) => {
debug!( debug!(
@ -131,10 +131,10 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
( (
Some( Some(
rl::Region::Static rbv::ResolvedArg::StaticLifetime
| rl::Region::Free(_, _) | rbv::ResolvedArg::Free(_, _)
| rl::Region::EarlyBound(_) | rbv::ResolvedArg::EarlyBound(_)
| rl::Region::LateBound(_, _, _), | rbv::ResolvedArg::LateBound(_, _, _),
) )
| None, | None,
_, _,
@ -186,9 +186,9 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
} }
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { 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! // 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); debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id { if id == def_id {
self.found_it = true; 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!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id); debug!("id={:?}", id);
debug!("def_id={:?}", def_id); debug!("def_id={:?}", def_id);
@ -208,10 +208,10 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
( (
Some( Some(
rl::Region::Static rbv::ResolvedArg::StaticLifetime
| rl::Region::EarlyBound(_) | rbv::ResolvedArg::EarlyBound(_)
| rl::Region::LateBound(_, _, _) | rbv::ResolvedArg::LateBound(_, _, _)
| rl::Region::Free(_, _), | rbv::ResolvedArg::Free(_, _),
) )
| None, | None,
_, _,

View File

@ -158,7 +158,7 @@ impl<'tcx> Elaborator<'tcx> {
traits::ImplDerivedObligation(Box::new( traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause { traits::ImplDerivedObligationCause {
derived, derived,
impl_def_id: data.def_id(), impl_or_alias_def_id: data.def_id(),
impl_def_predicate_index: Some(index), impl_def_predicate_index: Some(index),
span, span,
}, },

View File

@ -2007,7 +2007,7 @@ impl ExplicitOutlivesRequirements {
inferred_outlives: &[ty::Region<'tcx>], inferred_outlives: &[ty::Region<'tcx>],
predicate_span: Span, predicate_span: Span,
) -> Vec<(usize, Span)> { ) -> Vec<(usize, Span)> {
use rustc_middle::middle::resolve_lifetime::Region; use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
bounds bounds
.iter() .iter()
@ -2017,8 +2017,8 @@ impl ExplicitOutlivesRequirements {
return None; return None;
}; };
let is_inferred = match tcx.named_region(lifetime.hir_id) { let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
Some(Region::EarlyBound(def_id)) => inferred_outlives Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
.iter() .iter()
.any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })), .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
_ => false, _ => false,
@ -2097,7 +2097,7 @@ impl ExplicitOutlivesRequirements {
impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { 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; let def_id = item.owner_id.def_id;
if let hir::ItemKind::Struct(_, hir_generics) 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) = let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
match where_predicate { match where_predicate {
hir::WherePredicate::RegionPredicate(predicate) => { hir::WherePredicate::RegionPredicate(predicate) => {
if let Some(Region::EarlyBound(region_def_id)) = if let Some(ResolvedArg::EarlyBound(region_def_id)) =
cx.tcx.named_region(predicate.lifetime.hir_id) cx.tcx.named_bound_var(predicate.lifetime.hir_id)
{ {
( (
Self::lifetimes_outliving_lifetime( Self::lifetimes_outliving_lifetime(

View File

@ -1541,8 +1541,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.tables.impl_defaultness.set_some(def_id.index, *defaultness); self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
self.tables.constness.set_some(def_id.index, *constness); 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 { 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); 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 Ok(mut an) = trait_def.ancestors(self.tcx, def_id) {
if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {

View File

@ -18,7 +18,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::metadata::ModChild; use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; 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::mir;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;

View File

@ -29,7 +29,7 @@ pub mod lib_features {
pub mod limits; pub mod limits;
pub mod privacy; pub mod privacy;
pub mod region; pub mod region;
pub mod resolve_lifetime; pub mod resolve_bound_vars;
pub mod stability; pub mod stability;
pub fn provide(providers: &mut crate::ty::query::Providers) { pub fn provide(providers: &mut crate::ty::query::Providers) {

View File

@ -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; use crate::ty;
@ -8,10 +8,10 @@ use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::HashStable; use rustc_macros::HashStable;
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum Region { pub enum ResolvedArg {
Static, StaticLifetime,
EarlyBound(/* lifetime decl */ DefId), EarlyBound(/* decl */ DefId),
LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId), LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
Free(DefId, /* lifetime 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 /// Maps the id of each lifetime reference to the lifetime decl
/// that it corresponds to. /// that it corresponds to.
#[derive(Default, HashStable, Debug)] #[derive(Default, HashStable, Debug)]
pub struct ResolveLifetimes { pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a /// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound /// `Region` describing how that region is bound
pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>, pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, ResolvedArg>>,
pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>, pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
} }

View File

@ -781,7 +781,7 @@ rustc_queries! {
separate_provide_extern separate_provide_extern
} }
query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> { query issue33140_self_ty(key: DefId) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> {
desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) } 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 /// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params. /// lifetimes directly on things like trait methods, because of trait params.
/// See `rustc_resolve::late::lifetimes for details. /// See `rustc_resolve::late::lifetimes for details.
query resolve_lifetimes(_: hir::OwnerId) -> &'tcx ResolveLifetimes { query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
arena_cache arena_cache
desc { "resolving lifetimes" } desc { "resolving lifetimes" }
} }
query named_region_map(_: hir::OwnerId) -> query named_variable_map(_: hir::OwnerId) ->
Option<&'tcx FxHashMap<ItemLocalId, Region>> { Option<&'tcx FxHashMap<ItemLocalId, ResolvedArg>> {
desc { "looking up a named region" } desc { "looking up a named region" }
} }
query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> { query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {

View File

@ -474,7 +474,11 @@ pub enum WellFormedLoc {
#[derive(TypeVisitable, TypeFoldable)] #[derive(TypeVisitable, TypeFoldable)]
pub struct ImplDerivedObligationCause<'tcx> { pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'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. /// The index of the derived predicate in the parent impl's predicates.
pub impl_def_predicate_index: Option<usize>, pub impl_def_predicate_index: Option<usize>,
pub span: Span, pub span: Span,

View File

@ -1,7 +1,9 @@
use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::LitToConstInput; use crate::mir::interpret::LitToConstInput;
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::HashStable; use rustc_macros::HashStable;
use std::fmt; use std::fmt;
@ -125,16 +127,27 @@ impl<'tcx> Const<'tcx> {
} }
} }
use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
match expr.kind { match expr.kind {
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { hir::ExprKind::Path(hir::QPath::Resolved(
// Find the name and index of the const parameter by indexing the generics of _,
// the parent item and construct a `ParamConst`. &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
let item_def_id = tcx.parent(def_id); )) => {
let generics = tcx.generics_of(item_def_id); match tcx.named_bound_var(expr.hir_id) {
let index = generics.param_def_id_to_index[&def_id]; Some(rbv::ResolvedArg::EarlyBound(_)) => {
let name = tcx.item_name(def_id); // Find the name and index of the const parameter by indexing the generics of
Some(tcx.mk_const(ty::ParamConst::new(index, name), ty)) // 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, _ => None,
} }

View File

@ -9,7 +9,7 @@ use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::struct_lint_level; use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_lifetime; use crate::middle::resolve_bound_vars;
use crate::middle::stability; use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation}; use crate::mir::interpret::{self, Allocation, ConstAllocation};
use crate::mir::{ use crate::mir::{
@ -2368,9 +2368,9 @@ impl<'tcx> TyCtxt<'tcx> {
Some(&*candidates) Some(&*candidates)
} }
pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> { pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
debug!(?id, "named_region"); 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 { pub fn is_late_bound(self, id: HirId) -> bool {

View File

@ -290,7 +290,7 @@ impl DeepRejectCtxt {
// Impls cannot contain these types as these cannot be named directly. // Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false, 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 // Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables. // treat generic parameters like placeholders or like inference variables.
@ -310,7 +310,7 @@ impl DeepRejectCtxt {
ty::Error(_) => true, ty::Error(_) => true,
ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Bound(..) => { ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
bug!("unexpected obligation type: {:?}", obligation_ty) bug!("unexpected obligation type: {:?}", obligation_ty)
} }
} }

View File

@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! {
crate::metadata::ModChild, crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::exported_symbols::SymbolExportInfo, crate::middle::exported_symbols::SymbolExportInfo,
crate::middle::resolve_lifetime::ObjectLifetimeDefault, crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs, crate::mir::ConstQualifs,
ty::AssocItemContainer, ty::AssocItemContainer,
ty::DeducedParamAttrs, ty::DeducedParamAttrs,

View File

@ -8,7 +8,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use crate::middle::lib_features::LibFeatures; use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::EffectiveVisibilities; 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::middle::stability::{self, DeprecationEntry};
use crate::mir; use crate::mir;
use crate::mir::interpret::GlobalId; use crate::mir::interpret::GlobalId;

View File

@ -47,8 +47,7 @@ fn has_back_edge(
return false; return false;
} }
// Check if any of the dominators of the node are also the node's successor. // Check if any of the dominators of the node are also the node's successor.
doms.dominators(node) doms.dominators(node).any(|dom| node_data.terminator().successors().any(|succ| succ == dom))
.any(|dom| node_data.terminator().successors().into_iter().any(|succ| succ == dom))
} }
fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) { fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) {

View File

@ -2,7 +2,7 @@ use either::Either;
use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::graph::dominators::Dominators;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec; 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::visit::*;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt}; use rustc_middle::ty::{ParamEnv, TyCtxt};

View File

@ -18,7 +18,7 @@ use rustc_hir::{
}; };
use rustc_hir::{MethodKind, Target, Unsafety}; use rustc_hir::{MethodKind, Target, Unsafety};
use rustc_middle::hir::nested_filter; 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::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{ParamEnv, TyCtxt}; use rustc_middle::ty::{ParamEnv, TyCtxt};

View File

@ -270,10 +270,11 @@ where
| ty::Ref(..) | ty::Ref(..)
| ty::FnPtr(..) | ty::FnPtr(..)
| ty::Param(..) | ty::Param(..)
| ty::Bound(..)
| ty::Error(_) | ty::Error(_)
| ty::GeneratorWitness(..) | ty::GeneratorWitness(..)
| ty::GeneratorWitnessMIR(..) => {} | ty::GeneratorWitnessMIR(..) => {}
ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { ty::Placeholder(..) | ty::Infer(..) => {
bug!("unexpected type: {:?}", ty) bug!("unexpected type: {:?}", ty)
} }
} }

View File

@ -21,7 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; 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::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; 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::ty::DefIdTree;
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks}; 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 { let res = match kind {
ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()), 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), _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
}; };
self.r.record_partial_res(param.id, PartialRes::new(res)); self.r.record_partial_res(param.id, PartialRes::new(res));

View File

@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse;
use crate::parse::ParseSess; use crate::parse::ParseSess;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::util::literal::LitError; 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_macros::Diagnostic;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> {
pub cgu_name: &'a str, pub cgu_name: &'a str,
} }
#[derive(Diagnostic)] pub struct FeatureGateError {
#[diag(session_feature_gate_error, code = "E0658")]
pub struct FeatureGateError<'a> {
#[primary_span]
pub span: MultiSpan, 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)] #[derive(Subdiagnostic)]

View File

@ -88,7 +88,7 @@ pub fn feature_err<'a>(
sess: &'a ParseSess, sess: &'a ParseSess,
feature: Symbol, feature: Symbol,
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
explain: &str, explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> { ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
feature_err_issue(sess, feature, span, GateIssue::Language, explain) feature_err_issue(sess, feature, span, GateIssue::Language, explain)
} }
@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>(
feature: Symbol, feature: Symbol,
span: impl Into<MultiSpan>, span: impl Into<MultiSpan>,
issue: GateIssue, issue: GateIssue,
explain: &str, explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> { ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let span = span.into(); let span = span.into();
@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>(
.map(|err| err.cancel()); .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); add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
err err
} }

View File

@ -1016,6 +1016,7 @@ symbols! {
non_ascii_idents, non_ascii_idents,
non_exhaustive, non_exhaustive,
non_exhaustive_omitted_patterns_lint, non_exhaustive_omitted_patterns_lint,
non_lifetime_binders,
non_modrs_mods, non_modrs_mods,
nontemporal_store, nontemporal_store,
noop_method_borrow, noop_method_borrow,

View File

@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> Option<(DefId, SubstsRef<'tcx>)> { ) -> Option<(DefId, SubstsRef<'tcx>)> {
let tcx = self.tcx; let tcx = self.tcx;
let param_env = obligation.param_env; 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 trait_self_ty = trait_ref.self_ty();
let mut self_match_impls = vec![]; let mut self_match_impls = vec![];

View File

@ -1056,7 +1056,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool { ) -> bool {
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); 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 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::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
let ty::Param(param) = inner_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() parent_trait_pred.print_modifiers_and_trait_path()
); );
let mut is_auto_trait = false; 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 { Some(Node::Item(hir::Item {
kind: hir::ItemKind::Trait(is_auto, ..), kind: hir::ItemKind::Trait(is_auto, ..),
ident, ident,

View File

@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// still be provided by a manual implementation for // still be provided by a manual implementation for
// this trait and type. // 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 // In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down // type is. Therefore, we cannot break it down
// into its constituent types. So we don't // into its constituent types. So we don't
@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
); );
self.infcx.probe(|_snapshot| { self.infcx.probe(|_snapshot| {
if obligation.has_non_region_late_bound() {
return;
}
// The code below doesn't care about regions, and the // The code below doesn't care about regions, and the
// self-ty here doesn't escape this probe, so just erase // self-ty here doesn't escape this probe, so just erase
// any LBR. // any LBR.

View File

@ -1189,7 +1189,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(|derived| { let cause = obligation.derived_cause(|derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause { ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived, derived,
impl_def_id, impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: None, impl_def_predicate_index: None,
span: obligation.cause.span, span: obligation.cause.span,
})) }))

View File

@ -2657,7 +2657,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| { let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause { ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived, derived,
impl_def_id: def_id, impl_or_alias_def_id: def_id,
impl_def_predicate_index: Some(index), impl_def_predicate_index: Some(index),
span, span,
})) }))

View File

@ -1,7 +1,9 @@
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_index::bit_set::BitSet; 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_session::config::TraitSolver;
use rustc_span::def_id::{DefId, CRATE_DEF_ID}; use rustc_span::def_id::{DefId, CRATE_DEF_ID};
use rustc_trait_selection::traits; 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`. /// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
/// ///
/// See [`ty::ImplOverlapKind::Issue33140`] for more details. /// See [`ty::ImplOverlapKind::Issue33140`] for more details.
fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> { fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'_>>> {
debug!("issue33140_self_ty({:?})", def_id); debug!("issue33140_self_ty({:?})", def_id);
let trait_ref = tcx let trait_ref = tcx
@ -394,7 +396,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
if self_ty_matches { if self_ty_matches {
debug!("issue33140_self_ty - MATCHES!"); debug!("issue33140_self_ty - MATCHES!");
Some(self_ty) Some(EarlyBinder(self_ty))
} else { } else {
debug!("issue33140_self_ty - non-matching self type"); debug!("issue33140_self_ty - non-matching self type");
None None

View File

@ -3502,8 +3502,10 @@ pub trait Iterator {
} }
} }
/// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of
/// of another. /// 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 /// # 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.].iter()), Some(Ordering::Equal));
/// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less)); /// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
/// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater)); /// 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); /// 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")] #[stable(feature = "iter_order", since = "1.5.0")]
fn partial_cmp<I>(self, other: I) -> Option<Ordering> fn partial_cmp<I>(self, other: I) -> Option<Ordering>
where where

View File

@ -58,9 +58,10 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v))); 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))); clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
args.extend(clippy_lint_levels); args.extend(clippy_lint_levels);
args.extend(builder.config.free_args.clone());
args args
} else { } else {
vec![] builder.config.free_args.clone()
} }
} }

View File

@ -97,6 +97,10 @@ pub struct Config {
pub cmd: Subcommand, pub cmd: Subcommand,
pub incremental: bool, pub incremental: bool,
pub dry_run: DryRun, pub dry_run: DryRun,
/// Arguments appearing after `--` to be forwarded to tools,
/// e.g. `--fix-broken` or test arguments.
pub free_args: Vec<String>,
/// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should. /// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should.
#[cfg(not(test))] #[cfg(not(test))]
download_rustc_commit: Option<String>, download_rustc_commit: Option<String>,
@ -866,6 +870,7 @@ impl Config {
config.keep_stage = flags.keep_stage; config.keep_stage = flags.keep_stage;
config.keep_stage_std = flags.keep_stage_std; config.keep_stage_std = flags.keep_stage_std;
config.color = flags.color; config.color = flags.color;
config.free_args = flags.free_args.clone().unwrap_or_default();
if let Some(value) = flags.deny_warnings { if let Some(value) = flags.deny_warnings {
config.deny_warnings = value; config.deny_warnings = value;
} }

View File

@ -80,6 +80,10 @@ pub struct Flags {
pub llvm_profile_generate: bool, pub llvm_profile_generate: bool,
pub llvm_bolt_profile_generate: bool, pub llvm_bolt_profile_generate: bool,
pub llvm_bolt_profile_use: Option<String>, pub llvm_bolt_profile_use: Option<String>,
/// Arguments appearing after `--` to be forwarded to tools,
/// e.g. `--fix-broken` or test arguments.
pub free_args: Option<Vec<String>>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -157,6 +161,12 @@ impl Default for Subcommand {
impl Flags { impl Flags {
pub fn parse(args: &[String]) -> 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( let mut subcommand_help = String::from(
"\ "\
Usage: x.py <subcommand> [options] [<paths>...] Usage: x.py <subcommand> [options] [<paths>...]
@ -709,6 +719,7 @@ Arguments:
llvm_profile_generate: matches.opt_present("llvm-profile-generate"), llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"), llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"),
llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"), llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"),
free_args,
} }
} }
} }

View File

@ -183,6 +183,7 @@ impl Step for Miri {
// Forward arguments. // Forward arguments.
miri.arg("--").arg("--target").arg(target.rustc_target_arg()); miri.arg("--").arg("--target").arg(target.rustc_target_arg());
miri.args(builder.config.cmd.args()); miri.args(builder.config.cmd.args());
miri.args(&builder.config.free_args);
// miri tests need to know about the stage sysroot // miri tests need to know about the stage sysroot
miri.env("MIRI_SYSROOT", &miri_sysroot); miri.env("MIRI_SYSROOT", &miri_sysroot);

View File

@ -1588,6 +1588,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
.collect(); .collect();
test_args.append(&mut builder.config.cmd.test_args()); 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 // On Windows, replace forward slashes in test-args by backslashes
// so the correct filters are passed to libtest // so the correct filters are passed to libtest

View File

@ -21,7 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
use rustc_hir::PredicateOrigin; use rustc_hir::PredicateOrigin;
use rustc_hir_analysis::hir_ty_to_ty; use rustc_hir_analysis::hir_ty_to_ty;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; 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::fold::ir::TypeFolder;
use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::TypeVisitable; 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 { 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( if let Some(
rl::Region::EarlyBound(node_id) rbv::ResolvedArg::EarlyBound(node_id)
| rl::Region::LateBound(_, _, node_id) | rbv::ResolvedArg::LateBound(_, _, node_id)
| rl::Region::Free(_, node_id), | rbv::ResolvedArg::Free(_, node_id),
) = def ) = def
{ {
if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {

View File

@ -129,7 +129,7 @@ fn external_generic_args<'tcx>(
}); });
GenericArgs::Parenthesized { inputs, output } GenericArgs::Parenthesized { inputs, output }
} else { } else {
GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() } GenericArgs::AngleBracketed { args: args.into(), bindings }
} }
} }

View File

@ -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 if let FnRetTy::Return(ty) = sig.decl.output
&& let Some((out, Mutability::Mut, _)) = get_ref_lm(ty) && 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<Vec<_>> = sig let args: Option<Vec<_>> = sig
.decl .decl
.inputs .inputs
.iter() .iter()
.filter_map(get_ref_lm) .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)) .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
.collect(); .collect();
if let Some(args) = args if let Some(args) = args

View File

@ -10,7 +10,7 @@ use std::path::Path;
const ENTRY_LIMIT: usize = 1000; const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually. // FIXME: The following limits should be reduced eventually.
const ROOT_ENTRY_LIMIT: usize = 940; 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) { fn check_entries(path: &Path, bad: &mut bool) {
for dir in Walk::new(&path.join("ui")) { for dir in Walk::new(&path.join("ui")) {

View File

@ -16,17 +16,24 @@ error: lifetime bounds cannot be used in this context
LL | type C = for<'b, 'a: 'b +> fn(); 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 --> $DIR/bounds-lifetime.rs:4:18
| |
LL | type D = for<'a, T> fn(); LL | type D = for<'a, T> fn();
| ^ | ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/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 --> $DIR/bounds-lifetime.rs:5:18
| |
LL | type E = dyn for<T> Fn(); LL | type E = dyn for<T> Fn();
| ^ | ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to 5 previous errors error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -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 --> $DIR/disallow-const.rs:4:15
| |
LL | for<const N: i32> || -> () {}; LL | for<const N: i32> || -> () {};
| ^ | ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -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 --> $DIR/disallow-ty.rs:4:9
| |
LL | for<T> || -> () {}; LL | for<T> || -> () {};
| ^ | ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -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 error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:19:29 --> $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; 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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to 8 previous errors error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,4 @@
fn foo() where for<T> T:, {}
//~^ ERROR only lifetime parameters can be used in this context
fn main() {}

View File

@ -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> T:, {}
| ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/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`.

View File

@ -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 --> $DIR/hrtb-wrong-kind.rs:1:18
| |
LL | fn a() where for<T> T: Copy {} LL | fn a() where for<T> T: Copy {}
| ^ | ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/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 --> $DIR/hrtb-wrong-kind.rs:4:24
| |
LL | fn b() where for<const C: usize> [(); C]: Copy {} LL | fn b() where for<const C: usize> [(); C]: Copy {}
| ^ | ^
|
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to 2 previous errors error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -88,12 +88,6 @@ error: expected identifier, found `>`
LL | type QuiteBroken = fn<const>(); LL | type QuiteBroken = fn<const>();
| ^ expected identifier | ^ 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 error[E0412]: cannot find type `T` in this scope
--> $DIR/recover-fn-ptr-with-generics.rs:5:27 --> $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) -> T; LL | type Identity = fn<T>(T) -> T;
| ^ not found in this scope | ^ 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 error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0412`. For more information about this error, try `rustc --explain E0412`.

View File

@ -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>(I);
impl<I: IteratorAlias> Foo<I> {
fn f() {}
}
fn main() {
Foo::<()>::f() //~ trait bounds were not satisfied
}

View File

@ -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>(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<I: IteratorAlias> Foo<I> {
| ^^^^^^^^^^^^^ ------
| |
| unsatisfied trait bound introduced here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

View File

@ -0,0 +1,19 @@
// check-pass
// Basic test that show's we can succesfully typeck a `for<T>` where clause.
#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete
trait Trait {}
impl<T: ?Sized> Trait for T {}
fn foo()
where
for<T> T: Trait,
{
}
fn main() {
foo();
}

View File

@ -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 <https://github.com/rust-lang/rust/issues/1> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View File

@ -0,0 +1,23 @@
// Error reporting for where `for<T> T: Trait` doesn't hold
#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete
trait Trait {}
fn fail()
where
for<T> T: Trait,
{}
fn auto_trait()
where
for<T> T: Send,
{}
fn main() {
fail();
//~^ ERROR the trait bound `T: Trait` is not satisfied
auto_trait();
//~^ ERROR `T` cannot be sent between threads safely
}

View File

@ -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 <https://github.com/rust-lang/rust/issues/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> 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> 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`.

View File

@ -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<T> {}
fn foo() -> &'static dyn for<T> Test<T> {
//~^ ERROR late-bound type parameter not allowed on trait object types
todo!()
}
fn main() {}

View File

@ -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 <https://github.com/rust-lang/rust/issues/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<T> Test<T> {
| ^
error: aborting due to previous error; 1 warning emitted

View File

@ -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<T> fn(T) {
//~^ ERROR late-bound type parameter not allowed on function pointer types
todo!()
}
fn main() {
foo()(1i32);
}

View File

@ -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 <https://github.com/rust-lang/rust/issues/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<T> fn(T) {
| ^
error: aborting due to previous error; 1 warning emitted