Auto merge of #114358 - matthiaskrgr:rollup-d810m9e, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #114178 (Account for macros when suggesting a new let binding) - #114199 (Don't unsize coerce infer vars in select in new solver) - #114301 (Don't check unnecessarily that impl trait is RPIT) - #114314 (Tweaks to `adt_sized_constraint`) - #114322 (Fix invalid slice coercion suggestion reported in turbofish) - #114340 ([rustc_attr][nit] Replace `filter` + `is_some` with `map_or`.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
7a5d2d0138
25 changed files with 168 additions and 69 deletions
|
@ -28,7 +28,7 @@ pub fn rust_version_symbol() -> Symbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_builtin_attr(attr: &Attribute) -> bool {
|
pub fn is_builtin_attr(attr: &Attribute) -> bool {
|
||||||
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
|
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AttrError {
|
enum AttrError {
|
||||||
|
|
|
@ -2133,13 +2133,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
self.current -= 1;
|
self.current -= 1;
|
||||||
}
|
}
|
||||||
fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) {
|
||||||
if self.span == expr.span {
|
if self.span == expr.span.source_callsite() {
|
||||||
self.found = self.current;
|
self.found = self.current;
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let source_info = self.body.source_info(location);
|
let source_info = self.body.source_info(location);
|
||||||
|
let proper_span = proper_span.source_callsite();
|
||||||
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
|
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
|
||||||
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
|
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
|
||||||
&& let Some(node) = self.infcx.tcx.hir().find(scope_data.lint_root)
|
&& let Some(node) = self.infcx.tcx.hir().find(scope_data.lint_root)
|
||||||
|
|
|
@ -1462,7 +1462,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
let traits: Vec<_> =
|
let traits: Vec<_> =
|
||||||
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
|
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
|
||||||
|
|
||||||
// Don't print `TyErr` to the user.
|
// Don't print `ty::Error` to the user.
|
||||||
self.report_ambiguous_associated_type(
|
self.report_ambiguous_associated_type(
|
||||||
span,
|
span,
|
||||||
&[qself_ty.to_string()],
|
&[qself_ty.to_string()],
|
||||||
|
|
|
@ -555,8 +555,8 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||||
for (region_a, region_a_idx) in ®ions {
|
for (region_a, region_a_idx) in ®ions {
|
||||||
// Ignore `'static` lifetimes for the purpose of this lint: it's
|
// Ignore `'static` lifetimes for the purpose of this lint: it's
|
||||||
// because we know it outlives everything and so doesn't give meaningful
|
// because we know it outlives everything and so doesn't give meaningful
|
||||||
// clues
|
// clues. Also ignore `ReError`, to avoid knock-down errors.
|
||||||
if let ty::ReStatic = **region_a {
|
if let ty::ReStatic | ty::ReError(_) = **region_a {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// For each region argument (e.g., `'a` in our example), check for a
|
// For each region argument (e.g., `'a` in our example), check for a
|
||||||
|
@ -599,8 +599,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||||
// on the GAT itself.
|
// on the GAT itself.
|
||||||
for (region_b, region_b_idx) in ®ions {
|
for (region_b, region_b_idx) in ®ions {
|
||||||
// Again, skip `'static` because it outlives everything. Also, we trivially
|
// Again, skip `'static` because it outlives everything. Also, we trivially
|
||||||
// know that a region outlives itself.
|
// know that a region outlives itself. Also ignore `ReError`, to avoid
|
||||||
if ty::ReStatic == **region_b || region_a == region_b {
|
// knock-down errors.
|
||||||
|
if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if region_known_to_outlive(
|
if region_known_to_outlive(
|
||||||
|
|
|
@ -795,7 +795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
/// Converts the types that the user supplied, in case that doing
|
/// Converts the types that the user supplied, in case that doing
|
||||||
/// so should yield an error, but returns back a signature where
|
/// so should yield an error, but returns back a signature where
|
||||||
/// all parameters are of type `TyErr`.
|
/// all parameters are of type `ty::Error`.
|
||||||
fn error_sig_of_closure(
|
fn error_sig_of_closure(
|
||||||
&self,
|
&self,
|
||||||
decl: &hir::FnDecl<'_>,
|
decl: &hir::FnDecl<'_>,
|
||||||
|
|
|
@ -2567,15 +2567,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
if let Some(infer::RelateParamBound(_, t, _)) = origin {
|
if let Some(infer::RelateParamBound(_, t, _)) = origin {
|
||||||
let return_impl_trait =
|
|
||||||
self.tcx.return_type_impl_trait(generic_param_scope).is_some();
|
|
||||||
let t = self.resolve_vars_if_possible(t);
|
let t = self.resolve_vars_if_possible(t);
|
||||||
match t.kind() {
|
match t.kind() {
|
||||||
// We've got:
|
// We've got:
|
||||||
// fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
|
// fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
|
||||||
// suggest:
|
// suggest:
|
||||||
// fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
// fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||||
ty::Closure(..) | ty::Alias(ty::Opaque, ..) if return_impl_trait => {
|
ty::Closure(..) | ty::Alias(ty::Opaque, ..) => {
|
||||||
new_binding_suggestion(&mut err, type_param_span);
|
new_binding_suggestion(&mut err, type_param_span);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -942,6 +942,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||||
generic_ty: Ty<'tcx>,
|
generic_ty: Ty<'tcx>,
|
||||||
min: ty::Region<'tcx>,
|
min: ty::Region<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
if let ty::ReError(_) = *min {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
match bound {
|
match bound {
|
||||||
VerifyBound::IfEq(verify_if_eq_b) => {
|
VerifyBound::IfEq(verify_if_eq_b) => {
|
||||||
let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
|
let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
|
||||||
|
|
|
@ -706,7 +706,7 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
query adt_sized_constraint(key: DefId) -> &'tcx [Ty<'tcx>] {
|
query adt_sized_constraint(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
|
||||||
desc { |tcx| "computing `Sized` constraints for `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing `Sized` constraints for `{}`", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -562,18 +562,10 @@ impl<'tcx> AdtDef<'tcx> {
|
||||||
tcx.adt_destructor(self.did())
|
tcx.adt_destructor(self.did())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a list of types such that `Self: Sized` if and only
|
/// Returns a list of types such that `Self: Sized` if and only if that
|
||||||
/// if that type is `Sized`, or `TyErr` if this type is recursive.
|
/// type is `Sized`, or `ty::Error` if this type has a recursive layout.
|
||||||
///
|
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
|
||||||
/// Oddly enough, checking that the sized-constraint is `Sized` is
|
tcx.adt_sized_constraint(self.did())
|
||||||
/// actually more expressive than checking all members:
|
|
||||||
/// the `Sized` trait is inductive, so an associated type that references
|
|
||||||
/// `Self` would prevent its containing ADT from being `Sized`.
|
|
||||||
///
|
|
||||||
/// Due to normalization being eager, this applies even if
|
|
||||||
/// the associated type is behind a pointer (e.g., issue #31299).
|
|
||||||
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
|
|
||||||
ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::definitions::Definitions;
|
use rustc_hir::definitions::Definitions;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{
|
use rustc_hir::{Constness, HirId, Node, TraitCandidate};
|
||||||
Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
|
|
||||||
};
|
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_query_system::dep_graph::DepNodeIndex;
|
use rustc_query_system::dep_graph::DepNodeIndex;
|
||||||
|
@ -1077,31 +1075,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
|
|
||||||
// `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
|
|
||||||
match self.hir().get_by_def_id(scope_def_id) {
|
|
||||||
Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
|
|
||||||
Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
|
|
||||||
Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
|
|
||||||
Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
|
|
||||||
_ => return None,
|
|
||||||
}
|
|
||||||
|
|
||||||
let ret_ty = self.type_of(scope_def_id).instantiate_identity();
|
|
||||||
match ret_ty.kind() {
|
|
||||||
ty::FnDef(_, _) => {
|
|
||||||
let sig = ret_ty.fn_sig(self);
|
|
||||||
let output = self.erase_late_bound_regions(sig.output());
|
|
||||||
output.is_impl_trait().then(|| {
|
|
||||||
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
|
||||||
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
|
|
||||||
(output, fn_decl.output.span())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if the bound region is in Impl Item.
|
/// Checks if the bound region is in Impl Item.
|
||||||
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
|
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
|
||||||
let container_id = self.parent(suitable_region_binding_scope.to_def_id());
|
let container_id = self.parent(suitable_region_binding_scope.to_def_id());
|
||||||
|
|
|
@ -150,7 +150,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
||||||
|
|
||||||
ty::Adt(def, args) => {
|
ty::Adt(def, args) => {
|
||||||
let sized_crit = def.sized_constraint(ecx.tcx());
|
let sized_crit = def.sized_constraint(ecx.tcx());
|
||||||
Ok(sized_crit.iter_instantiated_copied(ecx.tcx(), args).collect())
|
Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,10 @@ fn rematch_unsize<'tcx>(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
&mut nested,
|
&mut nested,
|
||||||
);
|
);
|
||||||
|
|
||||||
match (a_ty.kind(), b_ty.kind()) {
|
match (a_ty.kind(), b_ty.kind()) {
|
||||||
|
// Don't try to coerce `?0` to `dyn Trait`
|
||||||
|
(ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => Ok(None),
|
||||||
// Stall any ambiguous upcasting goals, since we can't rematch those
|
// Stall any ambiguous upcasting goals, since we can't rematch those
|
||||||
(ty::Dynamic(_, _, ty::Dyn), ty::Dynamic(_, _, ty::Dyn)) => match certainty {
|
(ty::Dynamic(_, _, ty::Dyn), ty::Dynamic(_, _, ty::Dyn)) => match certainty {
|
||||||
Certainty::Yes => Ok(Some(ImplSource::Builtin(source, nested))),
|
Certainty::Yes => Ok(Some(ImplSource::Builtin(source, nested))),
|
||||||
|
|
|
@ -3030,8 +3030,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err);
|
self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.maybe_suggest_convert_to_slice(
|
self.suggest_convert_to_slice(
|
||||||
err,
|
err,
|
||||||
|
obligation,
|
||||||
trait_ref,
|
trait_ref,
|
||||||
impl_candidates.as_slice(),
|
impl_candidates.as_slice(),
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -398,9 +398,10 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
|
) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
|
||||||
|
|
||||||
fn maybe_suggest_convert_to_slice(
|
fn suggest_convert_to_slice(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
obligation: &PredicateObligation<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
candidate_impls: &[ImplCandidate<'tcx>],
|
candidate_impls: &[ImplCandidate<'tcx>],
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -3944,13 +3945,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
/// If the type that failed selection is an array or a reference to an array,
|
/// If the type that failed selection is an array or a reference to an array,
|
||||||
/// but the trait is implemented for slices, suggest that the user converts
|
/// but the trait is implemented for slices, suggest that the user converts
|
||||||
/// the array into a slice.
|
/// the array into a slice.
|
||||||
fn maybe_suggest_convert_to_slice(
|
fn suggest_convert_to_slice(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
obligation: &PredicateObligation<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
candidate_impls: &[ImplCandidate<'tcx>],
|
candidate_impls: &[ImplCandidate<'tcx>],
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
|
// We can only suggest the slice coersion for function arguments since the suggestion
|
||||||
|
// would make no sense in turbofish or call
|
||||||
|
let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
// Three cases where we can make a suggestion:
|
// Three cases where we can make a suggestion:
|
||||||
// 1. `[T; _]` (array of T)
|
// 1. `[T; _]` (array of T)
|
||||||
// 2. `&[T; _]` (reference to array of T)
|
// 2. `&[T; _]` (reference to array of T)
|
||||||
|
|
|
@ -2099,7 +2099,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
Where(
|
Where(
|
||||||
obligation
|
obligation
|
||||||
.predicate
|
.predicate
|
||||||
.rebind(sized_crit.iter_instantiated_copied(self.tcx(), args).collect()),
|
.rebind(sized_crit.iter_instantiated(self.tcx(), args).collect()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn sized_constraint_for_ty<'tcx>(
|
||||||
let adt_tys = adt.sized_constraint(tcx);
|
let adt_tys = adt.sized_constraint(tcx);
|
||||||
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
|
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
|
||||||
adt_tys
|
adt_tys
|
||||||
.iter_instantiated_copied(tcx, args)
|
.iter_instantiated(tcx, args)
|
||||||
.flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
|
.flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,18 @@ fn sized_constraint_for_ty<'tcx>(
|
||||||
// we know that `T` is Sized and do not need to check
|
// we know that `T` is Sized and do not need to check
|
||||||
// it on the impl.
|
// it on the impl.
|
||||||
|
|
||||||
let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] };
|
let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() else { return vec![ty] };
|
||||||
let sized_predicate =
|
|
||||||
ty::TraitRef::new(tcx, sized_trait, [ty]).without_const().to_predicate(tcx);
|
|
||||||
let predicates = tcx.predicates_of(adtdef.did()).predicates;
|
let predicates = tcx.predicates_of(adtdef.did()).predicates;
|
||||||
if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
|
if predicates.iter().any(|(p, _)| {
|
||||||
|
p.as_trait_clause().is_some_and(|trait_pred| {
|
||||||
|
trait_pred.def_id() == sized_trait_def_id
|
||||||
|
&& trait_pred.self_ty().skip_binder() == ty
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
vec![ty]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Placeholder(..) | Bound(..) | Infer(..) => {
|
Placeholder(..) | Bound(..) | Infer(..) => {
|
||||||
|
@ -92,10 +99,13 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
|
||||||
/// - a tuple of type parameters or projections, if there are multiple
|
/// - a tuple of type parameters or projections, if there are multiple
|
||||||
/// such.
|
/// such.
|
||||||
/// - an Error, if a type is infinitely sized
|
/// - an Error, if a type is infinitely sized
|
||||||
fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
|
fn adt_sized_constraint<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
) -> ty::EarlyBinder<&'tcx ty::List<Ty<'tcx>>> {
|
||||||
if let Some(def_id) = def_id.as_local() {
|
if let Some(def_id) = def_id.as_local() {
|
||||||
if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
|
if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
|
||||||
return tcx.mk_type_list(&[Ty::new_misc_error(tcx)]);
|
return ty::EarlyBinder::bind(tcx.mk_type_list(&[Ty::new_misc_error(tcx)]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let def = tcx.adt_def(def_id);
|
let def = tcx.adt_def(def_id);
|
||||||
|
@ -107,7 +117,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
|
||||||
|
|
||||||
debug!("adt_sized_constraint: {:?} => {:?}", def, result);
|
debug!("adt_sized_constraint: {:?} => {:?}", def, result);
|
||||||
|
|
||||||
result
|
ty::EarlyBinder::bind(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See `ParamEnv` struct definition for details.
|
/// See `ParamEnv` struct definition for details.
|
||||||
|
|
|
@ -8,8 +8,12 @@ LL | let x = defer(&vec!["Goodbye", "world!"]);
|
||||||
LL | x.x[0];
|
LL | x.x[0];
|
||||||
| ------ borrow later used here
|
| ------ borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
|
||||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = vec!["Goodbye", "world!"];
|
||||||
|
LL ~ let x = defer(&binding);
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
13
tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.rs
Normal file
13
tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
trait Test {}
|
||||||
|
impl Test for &[u8] {}
|
||||||
|
|
||||||
|
fn needs_test<T: Test>() -> T {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
needs_test::<[u8; 1]>();
|
||||||
|
//~^ ERROR the trait bound
|
||||||
|
let x: [u8; 1] = needs_test();
|
||||||
|
//~^ ERROR the trait bound
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied
|
||||||
|
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:9:18
|
||||||
|
|
|
||||||
|
LL | needs_test::<[u8; 1]>();
|
||||||
|
| ^^^^^^^ the trait `Test` is not implemented for `[u8; 1]`
|
||||||
|
|
|
||||||
|
= help: the trait `Test` is implemented for `&[u8]`
|
||||||
|
note: required by a bound in `needs_test`
|
||||||
|
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:4:18
|
||||||
|
|
|
||||||
|
LL | fn needs_test<T: Test>() -> T {
|
||||||
|
| ^^^^ required by this bound in `needs_test`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied
|
||||||
|
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:11:22
|
||||||
|
|
|
||||||
|
LL | let x: [u8; 1] = needs_test();
|
||||||
|
| ^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]`
|
||||||
|
|
|
||||||
|
= help: the trait `Test` is implemented for `&[u8]`
|
||||||
|
note: required by a bound in `needs_test`
|
||||||
|
--> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:4:18
|
||||||
|
|
|
||||||
|
LL | fn needs_test<T: Test>() -> T {
|
||||||
|
| ^^^^ required by this bound in `needs_test`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,12 @@
|
||||||
|
#![feature(return_position_impl_trait_in_trait)]
|
||||||
|
|
||||||
|
trait Iterable {
|
||||||
|
type Item<'a>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn iter(&self) -> impl Iterator<Item = Self::Item<'missing>>;
|
||||||
|
//~^ ERROR use of undeclared lifetime name `'missing`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,23 @@
|
||||||
|
error[E0261]: use of undeclared lifetime name `'missing`
|
||||||
|
--> $DIR/missing-lt-outlives-in-rpitit-114274.rs:8:55
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Self::Item<'missing>>;
|
||||||
|
| ^^^^^^^^ undeclared lifetime
|
||||||
|
|
|
||||||
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||||
|
help: consider making the bound lifetime-generic with a new `'missing` lifetime
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>>;
|
||||||
|
| +++++++++++++
|
||||||
|
help: consider introducing lifetime `'missing` here
|
||||||
|
|
|
||||||
|
LL | fn iter<'missing>(&self) -> impl Iterator<Item = Self::Item<'missing>>;
|
||||||
|
| ++++++++++
|
||||||
|
help: consider introducing lifetime `'missing` here
|
||||||
|
|
|
||||||
|
LL | trait Iterable<'missing> {
|
||||||
|
| ++++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0261`.
|
|
@ -1,4 +1,6 @@
|
||||||
// run-pass
|
// check-pass
|
||||||
|
// revisions: current next
|
||||||
|
//[next] compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
|
@ -9,8 +9,12 @@ LL |
|
||||||
LL | x.use_mut();
|
LL | x.use_mut();
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
|
||||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = vec![1];
|
||||||
|
LL ~ let mut x = binding.iter();
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,12 @@ LL |
|
||||||
LL | stuff(phantom_pinned)
|
LL | stuff(phantom_pinned)
|
||||||
| -------------- borrow later used here
|
| -------------- borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
|
||||||
= note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = pin!(PhantomPinned);
|
||||||
|
LL ~ let phantom_pinned = identity(binding);
|
||||||
|
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30
|
--> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30
|
||||||
|
|
17
tests/ui/traits/new-solver/dont-coerce-infer-to-dyn.rs
Normal file
17
tests/ui/traits/new-solver/dont-coerce-infer-to-dyn.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
fn mk<T: ?Sized>(t: Option<&T>) -> Rc<T> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut x = None;
|
||||||
|
let y = mk(x);
|
||||||
|
// Don't treat the line below as a unsize coercion `Rc<?0> ~> Rc<dyn Display>`
|
||||||
|
let z: Rc<dyn Display> = y;
|
||||||
|
x = Some(&1 as &dyn Display);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue