mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #108998 - matthiaskrgr:rollup-sxbdulg, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #106921 (Add documentation about the memory layout of `Cell`) - #108828 (Emit alias-eq when equating numeric var and projection) - #108834 (Do not ICE when we have fn pointer `Fn` obligations with bound vars in the self type) - #108900 (fix(lexer): print whitespace warning for \x0c) - #108930 (feat: implement better error for manual impl of `Fn*` traits) - #108937 (improve readability of winnowing) - #108947 (Don't even try to combine consts with incompatible types) - #108976 (Update triagebot rust-analyzer team mention) - #108983 (Forbid `#[target_feature]` on safe default implementations) Failed merges: - #108950 (Directly construct Inherited in typeck.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
19c53768af
@ -442,7 +442,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
|
||||
pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
|
||||
if let DefKind::AssocFn = tcx.def_kind(id) {
|
||||
let parent_id = tcx.local_parent(id);
|
||||
if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
|
||||
if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr_span,
|
||||
|
@ -42,6 +42,9 @@ hir_analysis_assoc_type_binding_not_allowed =
|
||||
associated type bindings are not allowed here
|
||||
.label = associated type not allowed here
|
||||
|
||||
hir_analysis_parenthesized_fn_trait_expansion =
|
||||
parenthesized trait syntax expands to `{$expanded_type}`
|
||||
|
||||
hir_analysis_typeof_reserved_keyword_used =
|
||||
`typeof` is a reserved keyword but unimplemented
|
||||
.suggestion = consider replacing `typeof(...)` with an actual type
|
||||
|
@ -1,10 +1,14 @@
|
||||
use crate::astconv::AstConv;
|
||||
use crate::errors::{ManualImplementation, MissingTypeParams};
|
||||
use crate::errors::{
|
||||
AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
|
||||
ParenthesizedFnTraitExpansion,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::traits::FulfillmentError;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
@ -78,43 +82,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
// Do not suggest the other syntax if we are in trait impl:
|
||||
// the desugaring would contain an associated type constraint.
|
||||
if !is_impl {
|
||||
let args = trait_segment
|
||||
.args
|
||||
.as_ref()
|
||||
.and_then(|args| args.args.get(0))
|
||||
.and_then(|arg| match arg {
|
||||
hir::GenericArg::Type(ty) => match ty.kind {
|
||||
hir::TyKind::Tup(t) => t
|
||||
.iter()
|
||||
.map(|e| sess.source_map().span_to_snippet(e.span))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map(|a| a.join(", ")),
|
||||
_ => sess.source_map().span_to_snippet(ty.span),
|
||||
}
|
||||
.map(|s| format!("({})", s))
|
||||
.ok(),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| "()".to_string());
|
||||
let ret = trait_segment
|
||||
.args()
|
||||
.bindings
|
||||
.iter()
|
||||
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
|
||||
(true, hir::TypeBindingKind::Equality { term }) => {
|
||||
let span = match term {
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(c) => self.tcx().hir().span(c.hir_id),
|
||||
};
|
||||
sess.source_map().span_to_snippet(span).ok()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| "()".to_string());
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use parenthetical notation instead",
|
||||
format!("{}{} -> {}", trait_segment.ident, args, ret),
|
||||
fn_trait_to_string(self.tcx(), trait_segment, true),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
@ -629,3 +600,69 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an error regarding forbidden type binding associations
|
||||
pub fn prohibit_assoc_ty_binding(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
segment: Option<(&hir::PathSegment<'_>, Span)>,
|
||||
) {
|
||||
tcx.sess.emit_err(AssocTypeBindingNotAllowed { span, fn_trait_expansion: if let Some((segment, span)) = segment && segment.args().parenthesized {
|
||||
Some(ParenthesizedFnTraitExpansion { span, expanded_type: fn_trait_to_string(tcx, segment, false) })
|
||||
} else {
|
||||
None
|
||||
}});
|
||||
}
|
||||
|
||||
pub(crate) fn fn_trait_to_string(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_segment: &hir::PathSegment<'_>,
|
||||
parenthesized: bool,
|
||||
) -> String {
|
||||
let args = trait_segment
|
||||
.args
|
||||
.as_ref()
|
||||
.and_then(|args| args.args.get(0))
|
||||
.and_then(|arg| match arg {
|
||||
hir::GenericArg::Type(ty) => match ty.kind {
|
||||
hir::TyKind::Tup(t) => t
|
||||
.iter()
|
||||
.map(|e| tcx.sess.source_map().span_to_snippet(e.span))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map(|a| a.join(", ")),
|
||||
_ => tcx.sess.source_map().span_to_snippet(ty.span),
|
||||
}
|
||||
.map(|s| {
|
||||
// `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
|
||||
if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) }
|
||||
})
|
||||
.ok(),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| "()".to_string());
|
||||
|
||||
let ret = trait_segment
|
||||
.args()
|
||||
.bindings
|
||||
.iter()
|
||||
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
|
||||
(true, hir::TypeBindingKind::Equality { term }) => {
|
||||
let span = match term {
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(c) => tcx.hir().span(c.hir_id),
|
||||
};
|
||||
|
||||
(span != tcx.hir().span(trait_segment.hir_id))
|
||||
.then_some(tcx.sess.source_map().span_to_snippet(span).ok())
|
||||
.flatten()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| "()".to_string());
|
||||
|
||||
if parenthesized {
|
||||
format!("{}{} -> {}", trait_segment.ident, args, ret)
|
||||
} else {
|
||||
format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use super::IsMethodCall;
|
||||
use crate::astconv::{
|
||||
CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
|
||||
GenericArgCountResult, GenericArgPosition,
|
||||
errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
|
||||
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
|
||||
};
|
||||
use crate::errors::AssocTypeBindingNotAllowed;
|
||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
|
||||
use rustc_ast::ast::ParamKindOrd;
|
||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
|
||||
@ -433,7 +432,7 @@ pub(crate) fn check_generic_arg_count(
|
||||
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
|
||||
|
||||
if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
|
||||
prohibit_assoc_ty_binding(tcx, b.span);
|
||||
prohibit_assoc_ty_binding(tcx, b.span, None);
|
||||
}
|
||||
|
||||
let explicit_late_bound =
|
||||
@ -589,11 +588,6 @@ pub(crate) fn check_generic_arg_count(
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an error regarding forbidden type binding associations
|
||||
pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
|
||||
tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
|
||||
}
|
||||
|
||||
/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
|
||||
/// are present. This is used both for datatypes and function calls.
|
||||
pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
||||
|
@ -5,9 +5,8 @@
|
||||
mod errors;
|
||||
pub mod generics;
|
||||
|
||||
use crate::astconv::generics::{
|
||||
check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
|
||||
};
|
||||
use crate::astconv::errors::prohibit_assoc_ty_binding;
|
||||
use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::HirPlaceholderCollector;
|
||||
use crate::errors::{
|
||||
@ -295,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
|
||||
}
|
||||
|
||||
substs
|
||||
@ -631,7 +630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
);
|
||||
|
||||
if let Some(b) = item_segment.args().bindings.first() {
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
|
||||
}
|
||||
|
||||
args
|
||||
@ -825,7 +824,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
constness,
|
||||
);
|
||||
if let Some(b) = trait_segment.args().bindings.first() {
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
|
||||
}
|
||||
self.tcx().mk_trait_ref(trait_def_id, substs)
|
||||
}
|
||||
@ -2596,7 +2595,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
for segment in segments {
|
||||
// Only emit the first error to avoid overloading the user with error messages.
|
||||
if let Some(b) = segment.args().bindings.first() {
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
||||
prohibit_assoc_ty_binding(self.tcx(), b.span, None);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +129,18 @@ pub struct AssocTypeBindingNotAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[help(hir_analysis_parenthesized_fn_trait_expansion)]
|
||||
pub struct ParenthesizedFnTraitExpansion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub expanded_type: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -148,13 +148,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
rhs_ty,
|
||||
op,
|
||||
);
|
||||
self.demand_suptype(expr.span, builtin_return_ty, return_ty);
|
||||
}
|
||||
|
||||
self.demand_eqtype(expr.span, builtin_return_ty, return_ty);
|
||||
builtin_return_ty
|
||||
} else {
|
||||
return_ty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_builtin_binop_types(
|
||||
&self,
|
||||
|
@ -411,15 +411,28 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
|
||||
ty::Infer(ty::IntVar(vid)) => {
|
||||
let nt = self.infcx.opportunistic_resolve_int_var(vid);
|
||||
if nt != t {
|
||||
return self.fold_ty(nt);
|
||||
} else {
|
||||
self.canonicalize_ty_var(
|
||||
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
|
||||
t,
|
||||
),
|
||||
|
||||
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
|
||||
)
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::FloatVar(vid)) => {
|
||||
let nt = self.infcx.opportunistic_resolve_float_var(vid);
|
||||
if nt != t {
|
||||
return self.fold_ty(nt);
|
||||
} else {
|
||||
self.canonicalize_ty_var(
|
||||
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
|
||||
t,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("encountered a fresh type during canonicalization")
|
||||
|
@ -34,7 +34,6 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::infer::canonical::OriginalQueryValues;
|
||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
||||
@ -119,20 +118,30 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.unify_float_variable(!a_is_expected, v_id, v)
|
||||
}
|
||||
|
||||
// We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
|
||||
(
|
||||
ty::Alias(AliasKind::Projection, _),
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
|
||||
)
|
||||
| (
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
|
||||
ty::Alias(AliasKind::Projection, _),
|
||||
) if self.tcx.trait_solver_next() => {
|
||||
bug!()
|
||||
}
|
||||
|
||||
(_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
|
||||
if self.tcx.trait_solver_next() =>
|
||||
{
|
||||
relation.register_type_equate_obligation(a, b);
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
// All other cases of inference are errors
|
||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
||||
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
|
||||
}
|
||||
|
||||
(ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
|
||||
relation.register_type_equate_obligation(a, b);
|
||||
Ok(b)
|
||||
}
|
||||
(_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
|
||||
relation.register_type_equate_obligation(b, a);
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
_ => ty::relate::super_relate_tys(relation, a, b),
|
||||
}
|
||||
}
|
||||
@ -161,9 +170,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
//
|
||||
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
|
||||
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
|
||||
self.probe(|_| {
|
||||
let compatible_types = self.probe(|_| {
|
||||
if a.ty() == b.ty() {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
|
||||
@ -173,15 +182,24 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
(relation.param_env(), a.ty(), b.ty()),
|
||||
&mut OriginalQueryValues::default(),
|
||||
);
|
||||
|
||||
if let Err(NoSolution) = self.tcx.check_tys_might_be_eq(canonical) {
|
||||
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
&format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
|
||||
);
|
||||
}
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
// If the consts have differing types, just bail with a const error with
|
||||
// the expected const's type. Specifically, we don't want const infer vars
|
||||
// to do any type shapeshifting before and after resolution.
|
||||
if let Err(guar) = compatible_types {
|
||||
return Ok(self.tcx.const_error_with_guaranteed(
|
||||
if relation.a_is_expected() { a.ty() } else { b.ty() },
|
||||
guar,
|
||||
));
|
||||
}
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
(
|
||||
ty::ConstKind::Infer(InferConst::Var(a_vid)),
|
||||
|
@ -1363,6 +1363,28 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.inner.borrow_mut().const_unification_table().find(var)
|
||||
}
|
||||
|
||||
/// Resolves an int var to a rigid int type, if it was constrained to one,
|
||||
/// or else the root int var in the unification table.
|
||||
pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
if let Some(value) = inner.int_unification_table().probe_value(vid) {
|
||||
value.to_type(self.tcx)
|
||||
} else {
|
||||
self.tcx.mk_int_var(inner.int_unification_table().find(vid))
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves a float var to a rigid int type, if it was constrained to one,
|
||||
/// or else the root float var in the unification table.
|
||||
pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
if let Some(value) = inner.float_unification_table().probe_value(vid) {
|
||||
value.to_type(self.tcx)
|
||||
} else {
|
||||
self.tcx.mk_float_var(inner.float_unification_table().find(vid))
|
||||
}
|
||||
}
|
||||
|
||||
/// Where possible, replaces type/const variables in
|
||||
/// `value` with their final value. Note that region variables
|
||||
/// are unaffected. If a type/const variable has not been unified, it
|
||||
|
@ -298,10 +298,10 @@ where
|
||||
}
|
||||
let tail = &tail[first_non_space..];
|
||||
if let Some(c) = tail.chars().nth(0) {
|
||||
if c.is_whitespace() {
|
||||
// For error reporting, we would like the span to contain the character that was not
|
||||
// skipped. The +1 is necessary to account for the leading \ that started the escape.
|
||||
let end = start + first_non_space + c.len_utf8() + 1;
|
||||
if c.is_whitespace() {
|
||||
callback(start..end, Err(EscapeError::UnskippedWhitespaceWarning));
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,9 @@ impl<'tcx> Const<'tcx> {
|
||||
_,
|
||||
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
|
||||
)) => {
|
||||
// Use the type from the param's definition, since we can resolve it,
|
||||
// not the expected parameter type from WithOptConstParam.
|
||||
let param_ty = tcx.type_of(def_id).subst_identity();
|
||||
match tcx.named_bound_var(expr.hir_id) {
|
||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||
// Find the name and index of the const parameter by indexing the generics of
|
||||
@ -143,14 +146,14 @@ impl<'tcx> Const<'tcx> {
|
||||
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(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
|
||||
}
|
||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
|
||||
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
|
||||
ty,
|
||||
param_ty,
|
||||
)),
|
||||
Some(rbv::ResolvedArg::Error(guar)) => {
|
||||
Some(tcx.const_error_with_guaranteed(ty, guar))
|
||||
Some(tcx.const_error_with_guaranteed(param_ty, guar))
|
||||
}
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
||||
}
|
||||
|
@ -995,7 +995,7 @@ impl<'tcx> Term<'tcx> {
|
||||
|
||||
pub fn is_infer(&self) -> bool {
|
||||
match self.unpack() {
|
||||
TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(),
|
||||
TermKind::Ty(ty) => ty.is_ty_var(),
|
||||
TermKind::Const(ct) => ct.is_ct_infer(),
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ parse_zero_chars = empty character literal
|
||||
parse_lone_slash = invalid trailing slash in literal
|
||||
.label = {parse_lone_slash}
|
||||
|
||||
parse_unskipped_whitespace = non-ASCII whitespace symbol '{$ch}' is not skipped
|
||||
parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
|
||||
.label = {parse_unskipped_whitespace}
|
||||
|
||||
parse_multiple_skipped_lines = multiple lines skipped by escaped newline
|
||||
|
@ -278,16 +278,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||
Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::IntVar(_)) => {
|
||||
let nt = self.infcx.shallow_resolve(t);
|
||||
ty::Infer(ty::IntVar(vid)) => {
|
||||
let nt = self.infcx.opportunistic_resolve_int_var(vid);
|
||||
if nt != t {
|
||||
return self.fold_ty(nt);
|
||||
} else {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::FloatVar(_)) => {
|
||||
let nt = self.infcx.shallow_resolve(t);
|
||||
ty::Infer(ty::FloatVar(vid)) => {
|
||||
let nt = self.infcx.opportunistic_resolve_float_var(vid);
|
||||
if nt != t {
|
||||
return self.fold_ty(nt);
|
||||
} else {
|
||||
|
@ -601,10 +601,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
debug!(?obligation, "confirm_fn_pointer_candidate");
|
||||
|
||||
let tcx = self.tcx();
|
||||
let self_ty = self
|
||||
|
||||
let Some(self_ty) = self
|
||||
.infcx
|
||||
.shallow_resolve(obligation.self_ty().no_bound_vars())
|
||||
.expect("fn pointer should not capture bound vars from predicate");
|
||||
.shallow_resolve(obligation.self_ty().no_bound_vars()) else
|
||||
{
|
||||
// FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
|
||||
// but we do not currently. Luckily, such a bound is not
|
||||
// particularly useful, so we don't expect users to write
|
||||
// them often.
|
||||
return Err(SelectionError::Unimplemented);
|
||||
};
|
||||
|
||||
let sig = self_ty.fn_sig(tcx);
|
||||
let trait_ref = closure_trait_ref_and_return_type(
|
||||
tcx,
|
||||
|
@ -465,14 +465,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
if candidates.len() > 1 {
|
||||
let mut i = 0;
|
||||
while i < candidates.len() {
|
||||
let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
|
||||
let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
|
||||
self.candidate_should_be_dropped_in_favor_of(
|
||||
&candidates[i],
|
||||
&candidates[j],
|
||||
needs_infer,
|
||||
)
|
||||
) == DropVictim::Yes
|
||||
});
|
||||
if is_dup {
|
||||
if should_drop_i {
|
||||
debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
|
||||
candidates.swap_remove(i);
|
||||
} else {
|
||||
@ -1842,16 +1842,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
ProjectionMatchesProjection::No
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// WINNOW
|
||||
//
|
||||
// Winnowing is the process of attempting to resolve ambiguity by
|
||||
// probing further. During the winnowing process, we unify all
|
||||
// type variables and then we also attempt to evaluate recursive
|
||||
// bounds to see if they are satisfied.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum DropVictim {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
/// Returns `true` if `victim` should be dropped in favor of
|
||||
/// ## Winnowing
|
||||
///
|
||||
/// Winnowing is the process of attempting to resolve ambiguity by
|
||||
/// probing further. During the winnowing process, we unify all
|
||||
/// type variables and then we also attempt to evaluate recursive
|
||||
/// bounds to see if they are satisfied.
|
||||
impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
/// Returns `DropVictim::Yes` if `victim` should be dropped in favor of
|
||||
/// `other`. Generally speaking we will drop duplicate
|
||||
/// candidates and prefer where-clause candidates.
|
||||
///
|
||||
@ -1861,9 +1867,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
victim: &EvaluatedCandidate<'tcx>,
|
||||
other: &EvaluatedCandidate<'tcx>,
|
||||
needs_infer: bool,
|
||||
) -> bool {
|
||||
) -> DropVictim {
|
||||
if victim.candidate == other.candidate {
|
||||
return true;
|
||||
return DropVictim::Yes;
|
||||
}
|
||||
|
||||
// Check if a bound would previously have been removed when normalizing
|
||||
@ -1887,11 +1893,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
// FIXME(@jswrenn): this should probably be more sophisticated
|
||||
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => false,
|
||||
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
|
||||
|
||||
// (*)
|
||||
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => true,
|
||||
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => false,
|
||||
(BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => {
|
||||
DropVictim::Yes
|
||||
}
|
||||
(_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => {
|
||||
DropVictim::No
|
||||
}
|
||||
|
||||
(ParamCandidate(other), ParamCandidate(victim)) => {
|
||||
let same_except_bound_vars = other.skip_binder().trait_ref
|
||||
@ -1905,28 +1915,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// or the current one if tied (they should both evaluate to the same answer). This is
|
||||
// probably best characterized as a "hack", since we might prefer to just do our
|
||||
// best to *not* create essentially duplicate candidates in the first place.
|
||||
other.bound_vars().len() <= victim.bound_vars().len()
|
||||
if other.bound_vars().len() <= victim.bound_vars().len() {
|
||||
DropVictim::Yes
|
||||
} else {
|
||||
DropVictim::No
|
||||
}
|
||||
} else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
|
||||
&& victim.skip_binder().constness == ty::BoundConstness::NotConst
|
||||
&& other.skip_binder().polarity == victim.skip_binder().polarity
|
||||
{
|
||||
// Drop otherwise equivalent non-const candidates in favor of const candidates.
|
||||
true
|
||||
DropVictim::Yes
|
||||
} else {
|
||||
false
|
||||
DropVictim::No
|
||||
}
|
||||
}
|
||||
|
||||
// Drop otherwise equivalent non-const fn pointer candidates
|
||||
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
|
||||
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => DropVictim::Yes,
|
||||
|
||||
// Global bounds from the where clause should be ignored
|
||||
// here (see issue #50825). Otherwise, we have a where
|
||||
// clause so don't go around looking for impls.
|
||||
// Arbitrarily give param candidates priority
|
||||
// over projection and object candidates.
|
||||
(
|
||||
ParamCandidate(ref cand),
|
||||
ParamCandidate(ref other_cand),
|
||||
ImplCandidate(..)
|
||||
| ClosureCandidate { .. }
|
||||
| GeneratorCandidate
|
||||
@ -1939,11 +1948,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| TraitAliasCandidate
|
||||
| ObjectCandidate(_)
|
||||
| ProjectionCandidate(..),
|
||||
) => !is_global(cand),
|
||||
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref cand)) => {
|
||||
) => {
|
||||
if is_global(other_cand) {
|
||||
DropVictim::No
|
||||
} else {
|
||||
// We have a where clause so don't go around looking
|
||||
// for impls. Arbitrarily give param candidates priority
|
||||
// over projection and object candidates.
|
||||
//
|
||||
// Global bounds from the where clause should be ignored
|
||||
// here (see issue #50825).
|
||||
DropVictim::Yes
|
||||
}
|
||||
}
|
||||
(ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref victim_cand)) => {
|
||||
// Prefer these to a global where-clause bound
|
||||
// (see issue #50825).
|
||||
is_global(cand)
|
||||
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
|
||||
}
|
||||
(
|
||||
ImplCandidate(_)
|
||||
@ -1956,18 +1977,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| TraitUpcastingUnsizeCandidate(_)
|
||||
| BuiltinCandidate { has_nested: true }
|
||||
| TraitAliasCandidate,
|
||||
ParamCandidate(ref cand),
|
||||
ParamCandidate(ref victim_cand),
|
||||
) => {
|
||||
// Prefer these to a global where-clause bound
|
||||
// (see issue #50825).
|
||||
is_global(cand) && other.evaluation.must_apply_modulo_regions()
|
||||
if is_global(victim_cand) && other.evaluation.must_apply_modulo_regions() {
|
||||
DropVictim::Yes
|
||||
} else {
|
||||
DropVictim::No
|
||||
}
|
||||
}
|
||||
|
||||
(ProjectionCandidate(i, _), ProjectionCandidate(j, _))
|
||||
| (ObjectCandidate(i), ObjectCandidate(j)) => {
|
||||
// Arbitrarily pick the lower numbered candidate for backwards
|
||||
// compatibility reasons. Don't let this affect inference.
|
||||
i < j && !needs_infer
|
||||
if i < j && !needs_infer { DropVictim::Yes } else { DropVictim::No }
|
||||
}
|
||||
(ObjectCandidate(_), ProjectionCandidate(..))
|
||||
| (ProjectionCandidate(..), ObjectCandidate(_)) => {
|
||||
@ -1987,7 +2012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| TraitUpcastingUnsizeCandidate(_)
|
||||
| BuiltinCandidate { .. }
|
||||
| TraitAliasCandidate,
|
||||
) => true,
|
||||
) => DropVictim::Yes,
|
||||
|
||||
(
|
||||
ImplCandidate(..)
|
||||
@ -2001,7 +2026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| BuiltinCandidate { .. }
|
||||
| TraitAliasCandidate,
|
||||
ObjectCandidate(_) | ProjectionCandidate(..),
|
||||
) => false,
|
||||
) => DropVictim::No,
|
||||
|
||||
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
|
||||
// See if we can toss out `victim` based on specialization.
|
||||
@ -2014,7 +2039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let tcx = self.tcx();
|
||||
if other.evaluation.must_apply_modulo_regions() {
|
||||
if tcx.specializes((other_def, victim_def)) {
|
||||
return true;
|
||||
return DropVictim::Yes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2060,13 +2085,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// will then correctly report an inference error, since the
|
||||
// existence of multiple marker trait impls tells us nothing
|
||||
// about which one should actually apply.
|
||||
!needs_infer
|
||||
if needs_infer { DropVictim::No } else { DropVictim::Yes }
|
||||
}
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
Some(_) => DropVictim::Yes,
|
||||
None => DropVictim::No,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
DropVictim::No
|
||||
}
|
||||
}
|
||||
|
||||
@ -2092,10 +2117,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| TraitUpcastingUnsizeCandidate(_)
|
||||
| BuiltinCandidate { has_nested: true }
|
||||
| TraitAliasCandidate,
|
||||
) => false,
|
||||
) => DropVictim::No,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
fn sized_conditions(
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
|
@ -99,10 +99,10 @@ pub fn translate_substs<'tcx>(
|
||||
}
|
||||
|
||||
fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
|
||||
|_| {
|
||||
|()| {
|
||||
bug!(
|
||||
"When translating substitutions for specialization, the expected \
|
||||
specialization failed to hold"
|
||||
"When translating substitutions from {source_impl:?} to {target_impl:?}, \
|
||||
the expected specialization failed to hold"
|
||||
)
|
||||
},
|
||||
)
|
||||
|
@ -209,6 +209,12 @@ pub use once::OnceCell;
|
||||
|
||||
/// A mutable memory location.
|
||||
///
|
||||
/// # Memory layout
|
||||
///
|
||||
/// `Cell<T>` has the same [memory layout and caveats as
|
||||
/// `UnsafeCell<T>`](UnsafeCell#memory-layout). In particular, this means that
|
||||
/// `Cell<T>` has the same in-memory representation as its inner type `T`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// In this example, you can see that `Cell<T>` enables mutation inside an
|
||||
|
@ -1,5 +1,6 @@
|
||||
fn foo<const N: usize>() -> [u8; N] {
|
||||
bar::<N>() //~ ERROR mismatched types
|
||||
//~^ ERROR the constant `N` is not of type `u8`
|
||||
}
|
||||
|
||||
fn bar<const N: u8>() -> [u8; N] {}
|
||||
|
@ -1,3 +1,15 @@
|
||||
error: the constant `N` is not of type `u8`
|
||||
--> $DIR/type_mismatch.rs:2:5
|
||||
|
|
||||
LL | bar::<N>()
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/type_mismatch.rs:6:8
|
||||
|
|
||||
LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| ^^^^^^^^^^^ required by this bound in `bar`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:2:11
|
||||
|
|
||||
@ -5,7 +17,7 @@ LL | bar::<N>()
|
||||
| ^ expected `u8`, found `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:5:26
|
||||
--> $DIR/type_mismatch.rs:6:26
|
||||
|
|
||||
LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| --- ^^^^^^^ expected `[u8; N]`, found `()`
|
||||
@ -13,11 +25,11 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:5:31
|
||||
--> $DIR/type_mismatch.rs:6:31
|
||||
|
|
||||
LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| ^ expected `usize`, found `u8`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -6,6 +6,5 @@ impl X {
|
||||
}
|
||||
fn getn<const N: cfg_attr>() -> [u8; N] {}
|
||||
//~^ ERROR expected type, found built-in attribute `cfg_attr`
|
||||
//~| ERROR mismatched types
|
||||
|
||||
fn main() {}
|
||||
|
@ -10,15 +10,7 @@ error[E0573]: expected type, found built-in attribute `cfg_attr`
|
||||
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
|
||||
| ^^^^^^^^ not a type
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_not_in_scope.rs:7:33
|
||||
|
|
||||
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
|
||||
| ---- ^^^^^^^ expected `[u8; N]`, found `()`
|
||||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0412, E0573.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
Some errors have detailed explanations: E0412, E0573.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
||||
|
@ -64,6 +64,12 @@ error[E0229]: associated type bindings are not allowed here
|
||||
|
|
||||
LL | impl FnOnce() for Foo1 {
|
||||
| ^^^^^^^^ associated type not allowed here
|
||||
|
|
||||
help: parenthesized trait syntax expands to `FnOnce<(), Output=()>`
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6
|
||||
|
|
||||
LL | impl FnOnce() for Foo1 {
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
|
||||
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6
|
||||
|
13
tests/ui/fn/issue-39259.rs
Normal file
13
tests/ui/fn/issue-39259.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#![feature(fn_traits)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
struct S;
|
||||
|
||||
impl Fn(u32) -> u32 for S {
|
||||
//~^ ERROR associated type bindings are not allowed here [E0229]
|
||||
fn call(&self) -> u32 {
|
||||
5
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
15
tests/ui/fn/issue-39259.stderr
Normal file
15
tests/ui/fn/issue-39259.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0229]: associated type bindings are not allowed here
|
||||
--> $DIR/issue-39259.rs:6:17
|
||||
|
|
||||
LL | impl Fn(u32) -> u32 for S {
|
||||
| ^^^ associated type not allowed here
|
||||
|
|
||||
help: parenthesized trait syntax expands to `Fn<(u32,), Output=u32>`
|
||||
--> $DIR/issue-39259.rs:6:6
|
||||
|
|
||||
LL | impl Fn(u32) -> u32 for S {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0229`.
|
19
tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr
Normal file
19
tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0277]: expected a `Fn<(&'w (),)>` closure, found `fn(&'w ())`
|
||||
--> $DIR/fn-ptr.rs:12:5
|
||||
|
|
||||
LL | ice();
|
||||
| ^^^ expected an `Fn<(&'w (),)>` closure, found `fn(&'w ())`
|
||||
|
|
||||
= help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())`
|
||||
note: required by a bound in `ice`
|
||||
--> $DIR/fn-ptr.rs:7:25
|
||||
|
|
||||
LL | fn ice()
|
||||
| --- required by a bound in this function
|
||||
LL | where
|
||||
LL | for<'w> fn(&'w ()): Fn(&'w ()),
|
||||
| ^^^^^^^^^^ required by this bound in `ice`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
14
tests/ui/higher-rank-trait-bounds/fn-ptr.rs
Normal file
14
tests/ui/higher-rank-trait-bounds/fn-ptr.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// revisions: classic next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
//[next] check-pass
|
||||
|
||||
fn ice()
|
||||
where
|
||||
for<'w> fn(&'w ()): Fn(&'w ()),
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {
|
||||
ice();
|
||||
//[classic]~^ ERROR expected a `Fn<(&'w (),)>` closure, found `fn(&'w ())`
|
||||
}
|
@ -1,16 +1,19 @@
|
||||
fn first() {
|
||||
second == 1 //~ ERROR binary operation
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn second() {
|
||||
first == 1 //~ ERROR binary operation
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
bar == 1 //~ ERROR binary operation
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -15,8 +15,16 @@ LL | second == 1
|
||||
= note: expected fn item `fn() {second}`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:2:5
|
||||
|
|
||||
LL | fn first() {
|
||||
| - help: try adding a return type: `-> bool`
|
||||
LL | second == 1
|
||||
| ^^^^^^^^^^^ expected `()`, found `bool`
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `fn() {first}`
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:7:11
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:8:11
|
||||
|
|
||||
LL | first == 1
|
||||
| ----- ^^ - {integer}
|
||||
@ -24,7 +32,7 @@ LL | first == 1
|
||||
| fn() {first}
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:7:14
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:8:14
|
||||
|
|
||||
LL | first == 1
|
||||
| ^ expected fn item, found integer
|
||||
@ -32,8 +40,16 @@ LL | first == 1
|
||||
= note: expected fn item `fn() {first}`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:8:5
|
||||
|
|
||||
LL | fn second() {
|
||||
| - help: try adding a return type: `-> bool`
|
||||
LL | first == 1
|
||||
| ^^^^^^^^^^ expected `()`, found `bool`
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `fn() {bar}`
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:12:9
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:14:9
|
||||
|
|
||||
LL | bar == 1
|
||||
| --- ^^ - {integer}
|
||||
@ -41,7 +57,7 @@ LL | bar == 1
|
||||
| fn() {bar}
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:12:12
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:14:12
|
||||
|
|
||||
LL | bar == 1
|
||||
| ^ expected fn item, found integer
|
||||
@ -49,7 +65,15 @@ LL | bar == 1
|
||||
= note: expected fn item `fn() {bar}`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-66667-function-cmp-cycle.rs:14:5
|
||||
|
|
||||
LL | fn bar() {
|
||||
| - help: try adding a return type: `-> bool`
|
||||
LL | bar == 1
|
||||
| ^^^^^^^^ expected `()`, found `bool`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0369.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -25,6 +25,12 @@ error[E0229]: associated type bindings are not allowed here
|
||||
|
|
||||
LL | impl Fn(&isize) for Error {
|
||||
| ^^^^^^^^^^ associated type not allowed here
|
||||
|
|
||||
help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
|
||||
--> $DIR/issue-95023.rs:3:6
|
||||
|
|
||||
LL | impl Fn(&isize) for Error {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0220]: associated type `B` not found for `Self`
|
||||
--> $DIR/issue-95023.rs:6:44
|
||||
|
@ -18,4 +18,10 @@ impl Foo for Bar {
|
||||
unsafe fn unsf_foo(&self) {}
|
||||
}
|
||||
|
||||
trait Qux {
|
||||
#[target_feature(enable = "sse2")]
|
||||
//~^ ERROR cannot be applied to safe trait method
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,3 +1,12 @@
|
||||
error: `#[target_feature(..)]` cannot be applied to safe trait method
|
||||
--> $DIR/trait-impl.rs:22:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
|
||||
LL |
|
||||
LL | fn foo(&self) {}
|
||||
| ------------- not an `unsafe` function
|
||||
|
||||
error: `#[target_feature(..)]` cannot be applied to safe trait method
|
||||
--> $DIR/trait-impl.rs:13:5
|
||||
|
|
||||
@ -7,5 +16,5 @@ LL |
|
||||
LL | fn foo(&self) {}
|
||||
| ------------- not an `unsafe` function
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
#![feature(min_specialization)]
|
||||
|
||||
// An impl that has an erroneous const substitution should not specialize one
|
||||
// that is well-formed.
|
||||
|
||||
struct S<const L: usize>;
|
||||
|
||||
impl<const N: i32> Copy for S<N> {}
|
||||
impl<const M: usize> Copy for S<M> {}
|
||||
//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>`
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,11 @@
|
||||
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
|
||||
--> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
|
||||
|
|
||||
LL | impl<const N: i32> Copy for S<N> {}
|
||||
| -------------------------------- first implementation here
|
||||
LL | impl<const M: usize> Copy for S<M> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
@ -1,11 +1,31 @@
|
||||
// check-pass
|
||||
// ignore-tidy-tab
|
||||
|
||||
fn main() {
|
||||
let s = "\
|
||||
|
||||
";
|
||||
//~^^^ WARNING multiple lines skipped by escaped newline
|
||||
assert_eq!(s, "");
|
||||
|
||||
let s = "foo\
|
||||
bar
|
||||
";
|
||||
//~^^^ WARNING non-ASCII whitespace symbol '\u{a0}' is not skipped
|
||||
//~^^^ WARNING whitespace symbol '\u{a0}' is not skipped
|
||||
assert_eq!(s, "foo bar\n ");
|
||||
|
||||
let s = "a\
|
||||
b";
|
||||
assert_eq!(s, "ab");
|
||||
|
||||
let s = "a\
|
||||
b";
|
||||
assert_eq!(s, "ab");
|
||||
|
||||
let s = "a\
|
||||
b";
|
||||
//~^^ WARNING whitespace symbol '\u{c}' is not skipped
|
||||
// '\x0c' is ASCII whitespace, but it may not need skipped
|
||||
// discussion: https://github.com/rust-lang/rust/pull/108403
|
||||
assert_eq!(s, "a\x0cb");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: multiple lines skipped by escaped newline
|
||||
--> $DIR/str-escape.rs:3:14
|
||||
--> $DIR/str-escape.rs:5:14
|
||||
|
|
||||
LL | let s = "\
|
||||
| ______________^
|
||||
@ -7,15 +7,25 @@ LL | |
|
||||
LL | | ";
|
||||
| |_____________^ skipping everything up to and including this point
|
||||
|
||||
warning: non-ASCII whitespace symbol '\u{a0}' is not skipped
|
||||
--> $DIR/str-escape.rs:7:17
|
||||
warning: whitespace symbol '\u{a0}' is not skipped
|
||||
--> $DIR/str-escape.rs:11:17
|
||||
|
|
||||
LL | let s = "foo\
|
||||
| _________________^
|
||||
LL | | bar
|
||||
| | ^ non-ASCII whitespace symbol '\u{a0}' is not skipped
|
||||
| | ^ whitespace symbol '\u{a0}' is not skipped
|
||||
| |___|
|
||||
|
|
||||
|
||||
warning: 2 warnings emitted
|
||||
warning: whitespace symbol '\u{c}' is not skipped
|
||||
--> $DIR/str-escape.rs:25:15
|
||||
|
|
||||
LL | let s = "a\
|
||||
| _______________^
|
||||
LL | | b";
|
||||
| | ^- whitespace symbol '\u{c}' is not skipped
|
||||
| |____|
|
||||
|
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
||||
|
@ -17,6 +17,12 @@ error[E0229]: associated type bindings are not allowed here
|
||||
|
|
||||
LL | impl Fn(&isize) for Error {
|
||||
| ^^^^^^^^^^ associated type not allowed here
|
||||
|
|
||||
help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
|
||||
--> $DIR/issue-87558.rs:3:6
|
||||
|
|
||||
LL | impl Fn(&isize) for Error {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
// check-pass
|
||||
|
||||
trait Mirror {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T> Mirror for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
trait Test {}
|
||||
impl Test for i64 {}
|
||||
impl Test for u64 {}
|
||||
|
||||
fn mirror_me<T: Mirror>(t: T, s: <T as Mirror>::Assoc) where <T as Mirror>::Assoc: Test {}
|
||||
|
||||
fn main() {
|
||||
let mut x = 0;
|
||||
mirror_me(x, 1);
|
||||
x = 1i64;
|
||||
}
|
18
tests/ui/traits/new-solver/int-var-alias-eq.rs
Normal file
18
tests/ui/traits/new-solver/int-var-alias-eq.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// check-pass
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
// HIR typeck ends up equating `<_#0i as Add>::Output == _#0i`.
|
||||
// Want to make sure that we emit an alias-eq goal for this,
|
||||
// instead of treating it as a type error and bailing.
|
||||
|
||||
fn test() {
|
||||
// fallback
|
||||
let x = 1 + 2;
|
||||
}
|
||||
|
||||
fn test2() -> u32 {
|
||||
// expectation from return ty
|
||||
1 + 2
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -6,7 +6,7 @@ mod assert {
|
||||
pub fn is_transmutable<Src, Context, const ASSUME_ALIGNMENT: bool>()
|
||||
where
|
||||
Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
|
||||
//~^ ERROR mismatched types
|
||||
//~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,15 @@ error[E0412]: cannot find type `Dst` in this scope
|
||||
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-101739-1.rs:8:50
|
||||
error: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
|
||||
--> $DIR/issue-101739-1.rs:8:14
|
||||
|
|
||||
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
|
||||
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `BikeshedIntrinsicFrom`
|
||||
--> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0412.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0412`.
|
||||
|
@ -1,5 +1,5 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
// known-bug: unknown
|
||||
// check-pass
|
||||
|
||||
fn main() {
|
||||
(0u8 + 0u8) as char;
|
||||
|
@ -1,9 +0,0 @@
|
||||
error[E0271]: type mismatch resolving `char == <u8 as Add>::Output`
|
||||
--> $DIR/cast-checks-handling-projections.rs:5:5
|
||||
|
|
||||
LL | (0u8 + 0u8) as char;
|
||||
| ^^^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -430,7 +430,7 @@ message = "The Miri subtree was changed"
|
||||
cc = ["@rust-lang/miri"]
|
||||
|
||||
[mentions."src/tools/rust-analyzer"]
|
||||
cc = ["@rust-lang/wg-rls-2"]
|
||||
cc = ["@rust-lang/rust-analyzer"]
|
||||
|
||||
[mentions."src/tools/rustfmt"]
|
||||
cc = ["@rust-lang/rustfmt"]
|
||||
|
Loading…
Reference in New Issue
Block a user