Move a wf-check into the site where the value is instantiated
This commit is contained in:
parent
1481fd964b
commit
8286ea5a49
8 changed files with 95 additions and 59 deletions
|
@ -36,7 +36,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
|
|||
use rustc_span::edition::Edition;
|
||||
use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::astconv_object_safety_violations;
|
||||
|
@ -275,6 +275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
item_segment.args(),
|
||||
item_segment.infer_args,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
|
@ -324,6 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
generic_args: &'a hir::GenericArgs<'_>,
|
||||
infer_args: bool,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
|
||||
// If the type is parameterized by this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
|
@ -534,6 +536,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
&mut substs_ctx,
|
||||
);
|
||||
|
||||
if let Some(ty::BoundConstness::ConstIfConst) = constness
|
||||
&& generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
tcx.sess.span_err(
|
||||
span,
|
||||
"~const can only be applied to `#[const_trait]` traits",
|
||||
);
|
||||
}
|
||||
|
||||
(substs, arg_count)
|
||||
}
|
||||
|
||||
|
@ -601,6 +612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
item_segment.args(),
|
||||
item_segment.infer_args,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
|
@ -620,6 +632,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
&self,
|
||||
trait_ref: &hir::TraitRef<'_>,
|
||||
self_ty: Ty<'tcx>,
|
||||
constness: ty::BoundConstness,
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
|
||||
|
||||
|
@ -629,6 +642,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty,
|
||||
trait_ref.path.segments.last().unwrap(),
|
||||
true,
|
||||
Some(constness),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -655,6 +669,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
args,
|
||||
infer_args,
|
||||
Some(self_ty),
|
||||
Some(constness),
|
||||
);
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
@ -680,6 +695,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
speculative,
|
||||
&mut dup_bindings,
|
||||
binding_span.unwrap_or(binding.span),
|
||||
constness,
|
||||
);
|
||||
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
|
||||
}
|
||||
|
@ -783,6 +799,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty: Ty<'tcx>,
|
||||
trait_segment: &hir::PathSegment<'_>,
|
||||
is_impl: bool,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
let (substs, _) = self.create_substs_for_ast_trait_ref(
|
||||
span,
|
||||
|
@ -790,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty,
|
||||
trait_segment,
|
||||
is_impl,
|
||||
constness,
|
||||
);
|
||||
if let Some(b) = trait_segment.args().bindings.first() {
|
||||
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
|
@ -805,6 +823,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
self_ty: Ty<'tcx>,
|
||||
trait_segment: &'a hir::PathSegment<'a>,
|
||||
is_impl: bool,
|
||||
constness: Option<ty::BoundConstness>,
|
||||
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
|
||||
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
|
||||
|
||||
|
@ -816,6 +835,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
trait_segment.args(),
|
||||
trait_segment.infer_args,
|
||||
Some(self_ty),
|
||||
constness,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1027,6 +1047,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
speculative: bool,
|
||||
dup_bindings: &mut FxHashMap<DefId, Span>,
|
||||
path_span: Span,
|
||||
constness: ty::BoundConstness,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// Given something like `U: SomeTrait<T = X>`, we want to produce a
|
||||
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
|
||||
|
@ -1122,10 +1143,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
trait_ref.substs,
|
||||
);
|
||||
|
||||
debug!(
|
||||
"add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}",
|
||||
substs_trait_ref_and_assoc_item
|
||||
);
|
||||
debug!(?substs_trait_ref_and_assoc_item);
|
||||
|
||||
ty::ProjectionTy {
|
||||
item_def_id: assoc_item.def_id,
|
||||
|
@ -1146,8 +1164,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
tcx.collect_constrained_late_bound_regions(&projection_ty);
|
||||
let late_bound_in_ty =
|
||||
tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty));
|
||||
debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
|
||||
debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
|
||||
debug!(?late_bound_in_trait_ref);
|
||||
debug!(?late_bound_in_ty);
|
||||
|
||||
// FIXME: point at the type params that don't have appropriate lifetimes:
|
||||
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
|
||||
|
@ -1648,6 +1666,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
// Checks that `bounds` contains exactly one element and reports appropriate
|
||||
// errors otherwise.
|
||||
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)]
|
||||
fn one_bound_for_assoc_type<I>(
|
||||
&self,
|
||||
all_candidates: impl Fn() -> I,
|
||||
|
@ -1677,10 +1696,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
return Err(reported);
|
||||
}
|
||||
};
|
||||
debug!("one_bound_for_assoc_type: bound = {:?}", bound);
|
||||
debug!(?bound);
|
||||
|
||||
if let Some(bound2) = next_cand {
|
||||
debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
|
||||
debug!(?bound2);
|
||||
|
||||
let is_equality = is_equality();
|
||||
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
|
||||
|
@ -1776,6 +1795,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
// parameter or `Self`.
|
||||
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
|
||||
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
|
||||
#[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)]
|
||||
pub fn associated_path_to_ty(
|
||||
&self,
|
||||
hir_ref_id: hir::HirId,
|
||||
|
@ -1793,8 +1813,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
Res::Err
|
||||
};
|
||||
|
||||
debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
|
||||
|
||||
// Check if we have an enum variant.
|
||||
let mut variant_resolution = None;
|
||||
if let ty::Adt(adt_def, _) = qself_ty.kind() {
|
||||
|
@ -2050,6 +2068,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
item_def_id: DefId,
|
||||
trait_segment: &hir::PathSegment<'_>,
|
||||
item_segment: &hir::PathSegment<'_>,
|
||||
constness: ty::BoundConstness,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
|
@ -2094,8 +2113,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
debug!("qpath_to_ty: self_type={:?}", self_ty);
|
||||
|
||||
let trait_ref =
|
||||
self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
|
||||
let trait_ref = self.ast_path_to_mono_trait_ref(
|
||||
span,
|
||||
trait_def_id,
|
||||
self_ty,
|
||||
trait_segment,
|
||||
false,
|
||||
Some(constness),
|
||||
);
|
||||
|
||||
let item_substs = self.create_substs_for_associated_item(
|
||||
span,
|
||||
|
@ -2534,12 +2559,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
Res::Def(DefKind::AssocTy, def_id) => {
|
||||
debug_assert!(path.segments.len() >= 2);
|
||||
self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {});
|
||||
// HACK: until we support `<Type as ~const Trait>`, assume all of them are.
|
||||
let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) {
|
||||
ty::BoundConstness::ConstIfConst
|
||||
} else {
|
||||
ty::BoundConstness::NotConst
|
||||
};
|
||||
self.qpath_to_ty(
|
||||
span,
|
||||
opt_self_ty,
|
||||
def_id,
|
||||
&path.segments[path.segments.len() - 2],
|
||||
path.segments.last().unwrap(),
|
||||
constness,
|
||||
)
|
||||
}
|
||||
Res::PrimTy(prim_ty) => {
|
||||
|
@ -2658,6 +2690,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
&GenericArgs::none(),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
|
||||
.subst(tcx, substs)
|
||||
|
@ -2766,6 +2799,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)]
|
||||
pub fn ty_of_fn(
|
||||
&self,
|
||||
hir_id: hir::HirId,
|
||||
|
@ -2775,8 +2809,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
generics: Option<&hir::Generics<'_>>,
|
||||
hir_ty: Option<&hir::Ty<'_>>,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
debug!("ty_of_fn");
|
||||
|
||||
let tcx = self.tcx();
|
||||
let bound_vars = tcx.late_bound_vars(hir_id);
|
||||
debug!(?bound_vars);
|
||||
|
@ -2826,7 +2858,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
|
||||
};
|
||||
|
||||
debug!("ty_of_fn: output_ty={:?}", output_ty);
|
||||
debug!(?output_ty);
|
||||
|
||||
let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
|
||||
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
|
||||
|
@ -2903,8 +2935,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
|
||||
hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
|
||||
|
||||
let trait_ref =
|
||||
self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
|
||||
let trait_ref = self.instantiate_mono_trait_ref(
|
||||
i.of_trait.as_ref()?,
|
||||
self.ast_ty_to_ty(i.self_ty),
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
|
||||
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
|
||||
tcx,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue