Auto merge of #106998 - matthiaskrgr:rollup-hmfisji, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #104505 (Remove double spaces after dots in comments) - #106784 (prevent E0512 from emitting [type error] by checking the references_error) - #106834 (new trait solver: only consider goal changed if response is not identity) - #106889 (Mention the lack of `windows_mut` in `windows`) - #106963 (Use `scope_expr_id` from `ProbeCtxt`) - #106970 (Switch to `EarlyBinder` for `item_bounds` query) - #106980 (Hide `_use_mk_alias_ty_instead` in `<AliasTy as Debug>::fmt`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
edefa4189f
173 changed files with 412 additions and 366 deletions
|
@ -99,12 +99,16 @@ pub(super) fn explicit_item_bounds(
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
|
||||
tcx.mk_predicates(
|
||||
pub(super) fn item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
|
||||
let bounds = tcx.mk_predicates(
|
||||
util::elaborate_predicates(
|
||||
tcx,
|
||||
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
|
||||
)
|
||||
.map(|obligation| obligation.predicate),
|
||||
)
|
||||
);
|
||||
ty::EarlyBinder(bounds)
|
||||
}
|
||||
|
|
|
@ -105,6 +105,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
|
||||
.note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
|
||||
let mut should_delay_as_bug = false;
|
||||
if let Err(LayoutError::Unknown(bad_from)) = sk_from && bad_from.references_error() {
|
||||
should_delay_as_bug = true;
|
||||
}
|
||||
if let Err(LayoutError::Unknown(bad_to)) = sk_to && bad_to.references_error() {
|
||||
should_delay_as_bug = true;
|
||||
}
|
||||
if should_delay_as_bug {
|
||||
err.delay_as_bug();
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
|
|
@ -486,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
probe_cx.assemble_inherent_candidates();
|
||||
match scope {
|
||||
ProbeScope::TraitsInScope => {
|
||||
probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)
|
||||
probe_cx.assemble_extension_candidates_for_traits_in_scope()
|
||||
}
|
||||
ProbeScope::AllTraits => probe_cx.assemble_extension_candidates_for_all_traits(),
|
||||
};
|
||||
|
@ -889,9 +889,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn assemble_extension_candidates_for_traits_in_scope(&mut self, expr_hir_id: hir::HirId) {
|
||||
fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
let opt_applicable_traits = self.tcx.in_scope_traits(expr_hir_id);
|
||||
let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
|
||||
if let Some(applicable_traits) = opt_applicable_traits {
|
||||
for trait_candidate in applicable_traits.iter() {
|
||||
let trait_did = trait_candidate.def_id;
|
||||
|
|
|
@ -298,7 +298,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
|||
substs: SubstsRef<'tcx>,
|
||||
) -> impl Iterator<Item = ty::Region<'tcx>> {
|
||||
let tcx = self.tcx;
|
||||
let bounds = tcx.bound_item_bounds(def_id);
|
||||
let bounds = tcx.item_bounds(def_id);
|
||||
trace!("{:#?}", bounds.0);
|
||||
bounds
|
||||
.subst_iter(tcx, substs)
|
||||
|
|
|
@ -68,6 +68,22 @@ pub struct CanonicalVarValues<'tcx> {
|
|||
pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
|
||||
}
|
||||
|
||||
impl CanonicalVarValues<'_> {
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
|
||||
ty::GenericArgKind::Lifetime(r) => {
|
||||
matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
|
||||
}
|
||||
ty::GenericArgKind::Type(ty) => {
|
||||
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
|
||||
}
|
||||
ty::GenericArgKind::Const(ct) => {
|
||||
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// When we canonicalize a value to form a query, we wind up replacing
|
||||
/// various parts of it with canonical variables. This struct stores
|
||||
/// those replaced bits to remember for when we process the query
|
||||
|
|
|
@ -272,7 +272,7 @@ rustc_queries! {
|
|||
/// ```
|
||||
///
|
||||
/// Bounds from the parent (e.g. with nested impl trait) are not included.
|
||||
query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
|
||||
query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
|
||||
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::mir::{Field, ProjectionKind};
|
|||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
||||
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
|
||||
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
|
||||
use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
|
||||
use rustc_data_structures::functor::IdFunctor;
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
|
@ -180,6 +180,15 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for AliasTy<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("AliasTy")
|
||||
.field("substs", &self.substs)
|
||||
.field("def_id", &self.def_id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Atomic structs
|
||||
//
|
||||
|
|
|
@ -1226,7 +1226,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
|
|||
/// For a projection, this would be `<Ty as Trait<...>>::N`.
|
||||
///
|
||||
/// For an opaque type, there is no explicit syntax.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct AliasTy<'tcx> {
|
||||
/// The parameters of the associated or opaque item.
|
||||
|
|
|
@ -659,13 +659,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
ty::EarlyBinder(self.explicit_item_bounds(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_item_bounds(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
|
||||
ty::EarlyBinder(self.item_bounds(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
|
||||
ty::EarlyBinder(self.impl_subject(def_id))
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ impl<'tcx> EvalCtxt<'tcx> {
|
|||
let canonical_goal = infcx.canonicalize_query(goal, &mut orig_values);
|
||||
let canonical_response = self.evaluate_canonical_goal(canonical_goal)?;
|
||||
Ok((
|
||||
true, // FIXME: check whether `var_values` are an identity substitution.
|
||||
!canonical_response.value.var_values.is_identity(),
|
||||
instantiate_canonical_query_response(infcx, &orig_values, canonical_response),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1123,7 +1123,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
|
||||
}
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
|
||||
self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
|
||||
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
|
||||
// args tuple will always be substs[1]
|
||||
|
|
|
@ -1375,7 +1375,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
|||
// Check whether the self-type is itself a projection.
|
||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||
let bounds = match *obligation.predicate.self_ty().kind() {
|
||||
ty::Alias(_, ref data) => tcx.bound_item_bounds(data.def_id).subst(tcx, data.substs),
|
||||
ty::Alias(_, ref data) => tcx.item_bounds(data.def_id).subst(tcx, data.substs),
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
// If the self-type is an inference variable, then it MAY wind up
|
||||
// being a projected type, so induce an ambiguity.
|
||||
|
|
|
@ -160,8 +160,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
_ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
|
||||
};
|
||||
|
||||
let candidate_predicate =
|
||||
tcx.bound_item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
|
||||
let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
|
||||
let candidate = candidate_predicate
|
||||
.to_opt_poly_trait_pred()
|
||||
.expect("projection candidate is not a trait predicate")
|
||||
|
@ -510,7 +509,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// This maybe belongs in wf, but that can't (doesn't) handle
|
||||
// higher-ranked things.
|
||||
// Prevent, e.g., `dyn Iterator<Item = str>`.
|
||||
for bound in self.tcx().bound_item_bounds(assoc_type).transpose_iter() {
|
||||
for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
|
||||
let subst_bound =
|
||||
if defs.count() == 0 {
|
||||
bound.subst(tcx, trait_predicate.trait_ref.substs)
|
||||
|
|
|
@ -1604,7 +1604,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
};
|
||||
let bounds = tcx.bound_item_bounds(def_id).subst(tcx, substs);
|
||||
let bounds = tcx.item_bounds(def_id).subst(tcx, substs);
|
||||
|
||||
// The bounds returned by `item_bounds` may contain duplicates after
|
||||
// normalization, so try to deduplicate when possible to avoid
|
||||
|
|
|
@ -781,6 +781,22 @@ impl<T> [T] {
|
|||
/// let mut iter = slice.windows(4);
|
||||
/// assert!(iter.next().is_none());
|
||||
/// ```
|
||||
///
|
||||
/// There's no `windows_mut`, as that existing would let safe code violate the
|
||||
/// "only one `&mut` at a time to the same thing" rule. However, you can sometimes
|
||||
/// use [`Cell::as_slice_of_cells`](crate::cell::Cell::as_slice_of_cells) in
|
||||
/// conjunction with `windows` to accomplish something similar:
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let mut array = ['R', 'u', 's', 't', ' ', '2', '0', '1', '5'];
|
||||
/// let slice = &mut array[..];
|
||||
/// let slice_of_cells: &[Cell<char>] = Cell::from_mut(slice).as_slice_of_cells();
|
||||
/// for w in slice_of_cells.windows(3) {
|
||||
/// Cell::swap(&w[0], &w[2]);
|
||||
/// }
|
||||
/// assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn windows(&self, size: usize) -> Windows<'_, T> {
|
||||
|
|
|
@ -647,8 +647,8 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
|
|||
Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
|
||||
},
|
||||
ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
|
||||
sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id), cx.tcx.opt_parent(def_id))
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id).subst(cx.tcx, substs), cx.tcx.opt_parent(def_id))
|
||||
},
|
||||
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
|
||||
ty::Dynamic(bounds, _, _) => {
|
||||
|
|
|
@ -45,6 +45,9 @@ C++ code used llvm_unreachable, which triggers undefined behavior
|
|||
when executed when assertions are disabled.
|
||||
Use llvm::report_fatal_error for increased robustness.";
|
||||
|
||||
const DOUBLE_SPACE_AFTER_DOT: &str = r"\
|
||||
Use a single space after dots in comments.";
|
||||
|
||||
const ANNOTATIONS_TO_IGNORE: &[&str] = &[
|
||||
"// @!has",
|
||||
"// @has",
|
||||
|
@ -279,6 +282,10 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
if filename.contains("ignore-tidy") {
|
||||
return;
|
||||
}
|
||||
// apfloat shouldn't be changed because of license problems
|
||||
if is_in(file, "compiler", "rustc_apfloat") {
|
||||
return;
|
||||
}
|
||||
let mut skip_cr = contains_ignore_directive(can_contain, &contents, "cr");
|
||||
let mut skip_undocumented_unsafe =
|
||||
contains_ignore_directive(can_contain, &contents, "undocumented-unsafe");
|
||||
|
@ -405,6 +412,19 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
|
||||
err(LLVM_UNREACHABLE_INFO);
|
||||
}
|
||||
|
||||
// For now only enforce in compiler
|
||||
let is_compiler = || file.components().any(|c| c.as_os_str() == "compiler");
|
||||
if is_compiler()
|
||||
&& line.contains("//")
|
||||
&& line
|
||||
.chars()
|
||||
.collect::<Vec<_>>()
|
||||
.windows(4)
|
||||
.any(|cs| matches!(cs, ['.', ' ', ' ', last] if last.is_alphabetic()))
|
||||
{
|
||||
err(DOUBLE_SPACE_AFTER_DOT)
|
||||
}
|
||||
}
|
||||
if leading_new_lines {
|
||||
let mut err = |_| {
|
||||
|
|
|
@ -37,7 +37,7 @@ LL | async fn foo(x: u32) -> u32 {
|
|||
= help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]`
|
||||
= note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited
|
||||
|
||||
error: internal compiler error: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:23:29: 25:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)`
|
||||
error: internal compiler error: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:23:29: 25:2]], def_id: ...) }, Term::Ty(u32)), []), depth=0)`
|
||||
--> $DIR/async.rs:23:25
|
||||
|
|
||||
LL | async fn foo(x: u32) -> u32 {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
type Bug<T, U> = impl Fn(T) -> U + Copy; //~ ERROR cycle detected
|
||||
|
||||
const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
//~^ ERROR: cannot transmute
|
||||
|
||||
fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
||||
|x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
|
||||
|
|
|
@ -24,23 +24,14 @@ LL | | CONST_BUG(0);
|
|||
LL | | }
|
||||
| |_^
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/issue-53092-2.rs:6:41
|
||||
|
|
||||
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[closure@$DIR/issue-53092-2.rs:6:61: 6:68]` (0 bits)
|
||||
= note: target type: `Bug<u8, ()>` (size can vary because of [type error])
|
||||
|
||||
error[E0277]: the trait bound `U: From<T>` is not satisfied
|
||||
--> $DIR/issue-53092-2.rs:10:5
|
||||
--> $DIR/issue-53092-2.rs:9:5
|
||||
|
|
||||
LL | |x| x.into()
|
||||
| ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
|
||||
|
|
||||
note: required by a bound in `make_bug`
|
||||
--> $DIR/issue-53092-2.rs:9:19
|
||||
--> $DIR/issue-53092-2.rs:8:19
|
||||
|
|
||||
LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
|
||||
| ^^^^^^^ required by this bound in `make_bug`
|
||||
|
@ -49,7 +40,7 @@ help: consider restricting type parameter `U`
|
|||
LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
|
||||
| +++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0391, E0512.
|
||||
Some errors have detailed explanations: E0277, E0391.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -15,5 +15,4 @@ mod foo {
|
|||
|
||||
fn main() {
|
||||
let _: foo::Foo = std::mem::transmute(0u8);
|
||||
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
|
|
|
@ -6,15 +6,5 @@ LL | pub type Foo = impl Copy;
|
|||
|
|
||||
= note: `Foo` must be used in combination with a concrete type within the same module
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/no_inferrable_concrete_type.rs:17:23
|
||||
|
|
||||
LL | let _: foo::Foo = std::mem::transmute(0u8);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `u8` (8 bits)
|
||||
= note: target type: `Foo` (size can vary because of [type error])
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0512`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue