Skip to content

Commit

Permalink
Auto merge of rust-lang#107400 - matthiaskrgr:rollup-l6bycds, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#107022 (Implement `SpecOptionPartialEq` for `cmp::Ordering`)
 - rust-lang#107100 (Use proper `InferCtxt` when probing for associated types in astconv)
 - rust-lang#107103 (Use new solver in `evaluate_obligation` query (when new solver is enabled))
 - rust-lang#107190 (Recover from more const arguments that are not wrapped in curly braces)
 - rust-lang#107306 (Correct suggestions for closure arguments that need a borrow)
 - rust-lang#107339 (internally change regions to be covariant)
 - rust-lang#107344 (Minor tweaks in the new solver)
 - rust-lang#107373 (Don't merge vtables when full debuginfo is enabled.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 28, 2023
2 parents 2527416 + c89bb15 commit 226b249
Show file tree
Hide file tree
Showing 39 changed files with 531 additions and 160 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,11 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
return;
}

// When full debuginfo is enabled, we want to try and prevent vtables from being
// merged. Otherwise debuggers will have a hard time mapping from dyn pointer
// to concrete type.
llvm::SetUnnamedAddress(vtable, llvm::UnnamedAddr::No);

let vtable_name =
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
let vtable_type_di_node = build_vtable_type_di_node(cx, ty, poly_trait_ref);
Expand Down
106 changes: 61 additions & 45 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
Expand All @@ -37,7 +37,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::{sym, Span};
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_target::spec::abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::astconv_object_safety_violations;
Expand All @@ -54,7 +54,7 @@ use std::slice;
pub struct PathSeg(pub DefId, pub usize);

pub trait AstConv<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
fn tcx(&self) -> TyCtxt<'tcx>;

fn item_def_id(&self) -> DefId;

Expand Down Expand Up @@ -131,6 +131,8 @@ pub trait AstConv<'tcx> {
{
self
}

fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
}

#[derive(Debug)]
Expand Down Expand Up @@ -2132,48 +2134,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
.emit() // Already reported in an earlier stage.
} else {
// Find all the `impl`s that `qself_ty` has for any trait that has the
// associated type, so that we suggest the right one.
let infcx = tcx.infer_ctxt().build();
// We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()`
// to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`.
let param_env = ty::ParamEnv::empty();
let traits: Vec<_> = self
.tcx()
.all_traits()
.filter(|trait_def_id| {
// Consider only traits with the associated type
tcx.associated_items(*trait_def_id)
.in_definition_order()
.any(|i| {
i.kind.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
&& matches!(i.kind, ty::AssocKind::Type)
})
// Consider only accessible traits
&& tcx.visibility(*trait_def_id)
.is_accessible_from(self.item_def_id(), tcx)
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
trait_ref.map_or(false, |trait_ref| {
let impl_ = trait_ref.subst(
tcx,
infcx.fresh_substs_for_item(span, impl_def_id),
);
infcx
.can_eq(
param_env,
tcx.erase_regions(impl_.self_ty()),
tcx.erase_regions(qself_ty),
)
.is_ok()
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
})
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
.collect();
let traits: Vec<_> =
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);

// Don't print `TyErr` to the user.
self.report_ambiguous_associated_type(
Expand Down Expand Up @@ -2232,6 +2194,60 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Ok((ty, DefKind::AssocTy, assoc_ty_did))
}

fn probe_traits_that_match_assoc_ty(
&self,
qself_ty: Ty<'tcx>,
assoc_ident: Ident,
) -> Vec<String> {
let tcx = self.tcx();

// In contexts that have no inference context, just make a new one.
// We do need a local variable to store it, though.
let infcx_;
let infcx = if let Some(infcx) = self.infcx() {
infcx
} else {
assert!(!qself_ty.needs_infer());
infcx_ = tcx.infer_ctxt().build();
&infcx_
};

tcx.all_traits()
.filter(|trait_def_id| {
// Consider only traits with the associated type
tcx.associated_items(*trait_def_id)
.in_definition_order()
.any(|i| {
i.kind.namespace() == Namespace::TypeNS
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
&& matches!(i.kind, ty::AssocKind::Type)
})
// Consider only accessible traits
&& tcx.visibility(*trait_def_id)
.is_accessible_from(self.item_def_id(), tcx)
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
trait_ref.map_or(false, |trait_ref| {
let impl_ = trait_ref.subst(
tcx,
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
);
infcx
.can_eq(
ty::ParamEnv::empty(),
tcx.erase_regions(impl_.self_ty()),
tcx.erase_regions(qself_ty),
)
.is_ok()
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
})
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
.collect()
}

fn lookup_assoc_ty(
&self,
ident: Ident,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericParamKind, Node};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::query::Providers;
Expand Down Expand Up @@ -517,6 +517,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
// There's no place to record types from signatures?
}

fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
None
}
}

/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_hir_analysis/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}

ty::Ref(region, ty, mutbl) => {
let contra = self.contravariant(variance);
self.add_constraints_from_region(current, region, contra);
self.add_constraints_from_region(current, region, variance);
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
}

Expand Down Expand Up @@ -258,9 +257,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}

ty::Dynamic(data, r, _) => {
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance);
self.add_constraints_from_region(current, r, contra);
// The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
self.add_constraints_from_region(current, r, variance);

if let Some(poly_trait_ref) = data.principal() {
self.add_constraints_from_invariant_substs(
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
let ty = if !ty.has_escaping_bound_vars() { self.normalize(span, ty) } else { ty };
self.write_ty(hir_id, ty)
}

fn infcx(&self) -> Option<&infer::InferCtxt<'tcx>> {
Some(&self.infcx)
}
}

/// Represents a user-provided type in the raw form (never normalized).
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);

let origin = Subtype(Box::new(self.fields.trace.clone()));
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
// GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
self.tcx(),
origin,
a,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);

let origin = Subtype(Box::new(self.fields.trace.clone()));
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
// LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
self.tcx(),
origin,
a,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,13 +663,13 @@ where
debug!(?v_b);

if self.ambient_covariance() {
// Covariance: a <= b. Hence, `b: a`.
self.push_outlives(v_b, v_a, self.ambient_variance_info);
// Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`.
self.push_outlives(v_a, v_b, self.ambient_variance_info);
}

if self.ambient_contravariance() {
// Contravariant: b <= a. Hence, `a: b`.
self.push_outlives(v_a, v_b, self.ambient_variance_info);
// Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`.
self.push_outlives(v_b, v_a, self.ambient_variance_info);
}

Ok(a)
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,13 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
// from the "cause" field, we could perhaps give more tailored
// error messages.
let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
// Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
self.fields
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.make_subregion(origin, a, b);
.make_subregion(origin, b, a);

Ok(a)
}
Expand Down
14 changes: 2 additions & 12 deletions compiler/rustc_middle/src/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
if a_repr == b_repr =>
{
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
relation.relate_with_variance(
ty::Contravariant,
ty::VarianceDiagInfo::default(),
a_region,
b_region,
)
relation.relate(a_region, b_region)
})?;
Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr))
}
Expand Down Expand Up @@ -497,12 +492,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
}

(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
let r = relation.relate_with_variance(
ty::Contravariant,
ty::VarianceDiagInfo::default(),
a_r,
b_r,
)?;
let r = relation.relate(a_r, b_r)?;
let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2353,6 +2353,28 @@ impl<'a> Parser<'a> {
Err(err)
}

/// Try to recover from an unbraced const argument whose first token [could begin a type][ty].
///
/// [ty]: token::Token::can_begin_type
pub(crate) fn recover_unbraced_const_arg_that_can_begin_ty(
&mut self,
mut snapshot: SnapshotParser<'a>,
) -> Option<P<ast::Expr>> {
match snapshot.parse_expr_res(Restrictions::CONST_EXPR, None) {
// Since we don't know the exact reason why we failed to parse the type or the
// expression, employ a simple heuristic to weed out some pathological cases.
Ok(expr) if let token::Comma | token::Gt = snapshot.token.kind => {
self.restore_snapshot(snapshot);
Some(expr)
}
Ok(_) => None,
Err(err) => {
err.cancel();
None
}
}
}

/// Creates a dummy const argument, and reports that the expression must be enclosed in braces
pub fn dummy_const_arg_needs_braces(
&self,
Expand Down
48 changes: 34 additions & 14 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,22 +675,42 @@ impl<'a> Parser<'a> {
GenericArg::Const(self.parse_const_arg()?)
} else if self.check_type() {
// Parse type argument.
let is_const_fn =
self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Parenthesis));
let mut snapshot = self.create_snapshot_for_diagnostic();

// Proactively create a parser snapshot enabling us to rewind and try to reparse the
// input as a const expression in case we fail to parse a type. If we successfully
// do so, we will report an error that it needs to be wrapped in braces.
let mut snapshot = None;
if self.may_recover() && self.token.can_begin_expr() {
snapshot = Some(self.create_snapshot_for_diagnostic());
}

match self.parse_ty() {
Ok(ty) => GenericArg::Type(ty),
Ok(ty) => {
// Since the type parser recovers from some malformed slice and array types and
// successfully returns a type, we need to look for `TyKind::Err`s in the
// type to determine if error recovery has occurred and if the input is not a
// syntactically valid type after all.
if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind
&& let ast::TyKind::Err = inner_ty.kind
&& let Some(snapshot) = snapshot
&& let Some(expr) = self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
{
return Ok(Some(self.dummy_const_arg_needs_braces(
self.struct_span_err(expr.span, "invalid const generic expression"),
expr.span,
)));
}

GenericArg::Type(ty)
}
Err(err) => {
if is_const_fn {
match (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None) {
Ok(expr) => {
self.restore_snapshot(snapshot);
return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
}
Err(err) => {
err.cancel();
}
}
if let Some(snapshot) = snapshot
&& let Some(expr) = self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
{
return Ok(Some(self.dummy_const_arg_needs_braces(
err,
expr.span,
)));
}
// Try to recover from possible `const` arg without braces.
return self.recover_const_arg(start, err).map(Some);
Expand Down
Loading

0 comments on commit 226b249

Please sign in to comment.