Auto merge of #126462 - matthiaskrgr:rollup-g0t1am4, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #123962 (change method resolution to constrain hidden types instead of rejecting method candidates) - #126244 (Update fuchsia commit, and SDK to 21.20240610.2.1) - #126270 (Migrate run make const fn mir) - #126320 (Avoid ICES after reporting errors on erroneous patterns) - #126449 (Fill out missing Windows support information) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
d2ad293851
@ -2888,7 +2888,7 @@ fn report_local_value_does_not_live_long_enough(
|
||||
..
|
||||
} = explanation
|
||||
{
|
||||
if let Some(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
borrow,
|
||||
borrow_span,
|
||||
span,
|
||||
@ -3075,7 +3075,7 @@ fn report_temporary_value_does_not_live_long_enough(
|
||||
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
|
||||
explanation
|
||||
{
|
||||
if let Some(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
|
||||
borrow,
|
||||
proper_span,
|
||||
span,
|
||||
@ -3237,11 +3237,11 @@ fn try_report_cannot_return_reference_to_local(
|
||||
return_span: Span,
|
||||
category: ConstraintCategory<'tcx>,
|
||||
opt_place_desc: Option<&String>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
let return_kind = match category {
|
||||
ConstraintCategory::Return(_) => "return",
|
||||
ConstraintCategory::Yield => "yield",
|
||||
_ => return None,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
// FIXME use a better heuristic than Spans
|
||||
@ -3317,7 +3317,7 @@ fn try_report_cannot_return_reference_to_local(
|
||||
}
|
||||
}
|
||||
|
||||
Some(err)
|
||||
Err(err)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
|
@ -628,7 +628,7 @@ fn suggest_call_as_method(
|
||||
return;
|
||||
};
|
||||
|
||||
let pick = self.confirm_method(
|
||||
let pick = self.confirm_method_for_diagnostic(
|
||||
call_expr.span,
|
||||
callee_expr,
|
||||
call_expr,
|
||||
|
@ -4,7 +4,7 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
@ -166,7 +166,7 @@ fn adjust_expr_for_assert_eq_macro(
|
||||
/// Requires that the two types unify, and prints an error message if
|
||||
/// they don't.
|
||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
|
||||
e.emit();
|
||||
}
|
||||
}
|
||||
@ -176,7 +176,7 @@ pub fn demand_suptype_diag(
|
||||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
@ -186,18 +186,15 @@ pub fn demand_suptype_with_origin(
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
None
|
||||
}
|
||||
Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
|
||||
}
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.at(cause, self.param_env)
|
||||
.sup(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
|
||||
}
|
||||
|
||||
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
@ -207,7 +204,7 @@ pub fn demand_eqtype_diag(
|
||||
sp: Span,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
|
||||
}
|
||||
|
||||
@ -216,14 +213,11 @@ pub fn demand_eqtype_with_origin(
|
||||
cause: &ObligationCause<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
None
|
||||
}
|
||||
Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
|
||||
}
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.at(cause, self.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, expected, actual)
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
|
||||
}
|
||||
|
||||
pub fn demand_coerce(
|
||||
@ -234,12 +228,17 @@ pub fn demand_coerce(
|
||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> Ty<'tcx> {
|
||||
let (ty, err) =
|
||||
self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
|
||||
if let Some(err) = err {
|
||||
err.emit();
|
||||
match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
|
||||
{
|
||||
Ok(ty) => ty,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
// Return the original type instead of an error type here, otherwise the type of `x` in
|
||||
// `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
|
||||
// report errors, even though `x` is definitely `u32`.
|
||||
expected
|
||||
}
|
||||
}
|
||||
ty
|
||||
}
|
||||
|
||||
/// Checks that the type of `expr` can be coerced to `expected`.
|
||||
@ -254,11 +253,11 @@ pub fn demand_coerce_diag(
|
||||
expected: Ty<'tcx>,
|
||||
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> (Ty<'tcx>, Option<Diag<'tcx>>) {
|
||||
) -> Result<Ty<'tcx>, Diag<'tcx>> {
|
||||
let expected = self.resolve_vars_with_obligations(expected);
|
||||
|
||||
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
|
||||
Ok(ty) => return (ty, None),
|
||||
Ok(ty) => return Ok(ty),
|
||||
Err(e) => e,
|
||||
};
|
||||
|
||||
@ -275,7 +274,7 @@ pub fn demand_coerce_diag(
|
||||
|
||||
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
|
||||
|
||||
(expected, Some(err))
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Notes the point at which a variable is constrained to some type incompatible
|
||||
|
@ -87,7 +87,7 @@ pub fn check_expr_has_type_or_error(
|
||||
ty = adj_ty;
|
||||
}
|
||||
|
||||
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||
if let Err(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||
let _ = self.emit_type_mismatch_suggestions(
|
||||
&mut err,
|
||||
expr.peel_drop_temps(),
|
||||
@ -1132,7 +1132,7 @@ fn check_expr_assign(
|
||||
// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
|
||||
// The likely cause of this is `if foo = bar { .. }`.
|
||||
let actual_ty = self.tcx.types.unit;
|
||||
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
|
||||
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
|
||||
let lhs_ty = self.check_expr(lhs);
|
||||
let rhs_ty = self.check_expr(rhs);
|
||||
let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
|
||||
@ -1236,7 +1236,7 @@ fn check_expr_assign(
|
||||
// This is (basically) inlined `check_expr_coercible_to_type`, but we want
|
||||
// to suggest an additional fixup here in `suggest_deref_binop`.
|
||||
let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
|
||||
if let (_, Some(mut diag)) =
|
||||
if let Err(mut diag) =
|
||||
self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
|
||||
{
|
||||
suggest_deref_binop(&mut diag, rhs_ty);
|
||||
@ -1738,10 +1738,9 @@ fn check_expr_struct_fields(
|
||||
// Make sure to give a type to the field even if there's
|
||||
// an error, so we can continue type-checking.
|
||||
let ty = self.check_expr_with_hint(field.expr, field_type);
|
||||
let (_, diag) =
|
||||
self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
|
||||
let diag = self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
|
||||
|
||||
if let Some(diag) = diag {
|
||||
if let Err(diag) = diag {
|
||||
if idx == hir_fields.len() - 1 {
|
||||
if remaining_fields.is_empty() {
|
||||
self.suggest_fru_from_range_and_emit(field, variant, args, diag);
|
||||
|
@ -1418,7 +1418,7 @@ fn inferred_kind(
|
||||
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
|
||||
let self_ty = self.normalize(span, self_ty);
|
||||
match self.at(&self.misc(span), self.param_env).eq(
|
||||
DefineOpaqueTypes::No,
|
||||
DefineOpaqueTypes::Yes,
|
||||
impl_ty,
|
||||
self_ty,
|
||||
) {
|
||||
|
@ -1578,7 +1578,7 @@ pub fn check_decl_initializer(
|
||||
// type of the place it is referencing, and not some
|
||||
// supertype thereof.
|
||||
let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
|
||||
if let Some(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
|
||||
if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
|
||||
self.emit_type_mismatch_suggestions(
|
||||
&mut diag,
|
||||
init.peel_drop_temps(),
|
||||
@ -1624,7 +1624,7 @@ pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) {
|
||||
let previous_diverges = self.diverges.get();
|
||||
let else_ty = self.check_block_with_expected(blk, NoExpectation);
|
||||
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
|
||||
if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
|
||||
if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
|
||||
{
|
||||
err.emit();
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ fn unify_receivers(
|
||||
args,
|
||||
})),
|
||||
);
|
||||
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
|
||||
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
}
|
||||
|
@ -634,8 +634,8 @@ fn assemble_inherent_candidates(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
|
||||
debug!("assemble_probe: self_ty={:?}", self_ty);
|
||||
let raw_self_ty = self_ty.value.value;
|
||||
match *raw_self_ty.kind() {
|
||||
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
|
||||
@ -713,13 +713,12 @@ fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
|
||||
if !self.impl_dups.insert(impl_def_id) {
|
||||
return; // already visited
|
||||
}
|
||||
|
||||
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
|
||||
|
||||
for item in self.impl_or_trait_item(impl_def_id) {
|
||||
if !self.has_applicable_self(&item) {
|
||||
// No receiver declared. Not a candidate.
|
||||
@ -737,9 +736,8 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
|
||||
debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
|
||||
|
||||
let principal = match self_ty.kind() {
|
||||
ty::Dynamic(ref data, ..) => Some(data),
|
||||
_ => None,
|
||||
@ -768,9 +766,9 @@ fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
|
||||
});
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
|
||||
// FIXME: do we want to commit to this behavior for param bounds?
|
||||
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
|
||||
|
||||
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
|
||||
let bound_predicate = predicate.kind();
|
||||
@ -826,6 +824,7 @@ fn elaborate_bounds<F>(
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
|
||||
@ -842,6 +841,7 @@ fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_all_traits(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
for trait_info in suggest::all_traits(self.tcx) {
|
||||
@ -863,12 +863,12 @@ fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_trait(
|
||||
&mut self,
|
||||
import_ids: &SmallVec<[LocalDefId; 1]>,
|
||||
trait_def_id: DefId,
|
||||
) {
|
||||
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
|
||||
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
|
||||
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
|
||||
|
||||
@ -958,6 +958,7 @@ fn candidate_method_names(
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// THE ACTUAL SEARCH
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn pick(mut self) -> PickResult<'tcx> {
|
||||
assert!(self.method_name.is_some());
|
||||
|
||||
@ -1386,6 +1387,7 @@ fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> Ca
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
|
||||
fn consider_probe(
|
||||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
@ -1415,15 +1417,8 @@ fn consider_probe(
|
||||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, impl_ty, impl_args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
@ -1484,19 +1479,23 @@ fn consider_probe(
|
||||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
match self_ty.kind() {
|
||||
// HACK: opaque types will match anything for which their bounds hold.
|
||||
// Thus we need to prevent them from trying to match the `&_` autoref
|
||||
// candidates that get created for `&self` trait methods.
|
||||
ty::Alias(ty::Opaque, alias_ty)
|
||||
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
|
||||
&& !xform_self_ty.is_ty_var() =>
|
||||
{
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
_ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
},
|
||||
}
|
||||
let obligation = traits::Obligation::new(
|
||||
self.tcx,
|
||||
@ -1536,15 +1535,8 @@ fn consider_probe(
|
||||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
@ -1665,6 +1657,7 @@ fn collapse_candidates_to_trait_pick(
|
||||
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
|
||||
/// candidate method where the method name may have been misspelled. Similarly to other
|
||||
/// edit distance based suggestions, we provide at most one such suggestion.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn probe_for_similar_candidate(
|
||||
&mut self,
|
||||
) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
|
||||
|
@ -105,15 +105,16 @@ fn demand_eqtype_pat_diag(
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: &TopInfo<'tcx>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
let mut diag =
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
|
||||
if let Some(expr) = ti.origin_expr {
|
||||
self.suggest_fn_call(&mut diag, expr, expected, |output| {
|
||||
self.can_eq(self.param_env, output, actual)
|
||||
});
|
||||
}
|
||||
Some(diag)
|
||||
) -> Result<(), Diag<'tcx>> {
|
||||
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
|
||||
.map_err(|mut diag| {
|
||||
if let Some(expr) = ti.origin_expr {
|
||||
self.suggest_fn_call(&mut diag, expr, expected, |output| {
|
||||
self.can_eq(self.param_env, output, actual)
|
||||
});
|
||||
}
|
||||
diag
|
||||
})
|
||||
}
|
||||
|
||||
fn demand_eqtype_pat(
|
||||
@ -122,10 +123,8 @@ fn demand_eqtype_pat(
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
ti: &TopInfo<'tcx>,
|
||||
) {
|
||||
if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
|
||||
err.emit();
|
||||
}
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,7 +508,7 @@ fn check_pat_lit(
|
||||
//
|
||||
// then that's equivalent to there existing a LUB.
|
||||
let cause = self.pattern_cause(ti, span);
|
||||
if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
|
||||
if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
|
||||
err.emit_unless(
|
||||
ti.span
|
||||
.filter(|&s| {
|
||||
@ -562,7 +561,7 @@ fn check_pat_range(
|
||||
// Subtyping doesn't matter here, as the value is some kind of scalar.
|
||||
let demand_eqtype = |x: &mut _, y| {
|
||||
if let Some((ref mut fail, x_ty, x_span)) = *x
|
||||
&& let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
|
||||
&& let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
|
||||
{
|
||||
if let Some((_, y_ty, y_span)) = y {
|
||||
self.endpoint_has_type(&mut err, y_span, y_ty);
|
||||
@ -736,7 +735,9 @@ fn check_pat_ident(
|
||||
// Otherwise, the type of x is the expected type `T`.
|
||||
ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
|
||||
};
|
||||
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
|
||||
|
||||
// We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
|
||||
let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
|
||||
|
||||
// If there are multiple arms, make sure they all agree on
|
||||
// what the type of the binding `x` ought to be.
|
||||
@ -763,7 +764,7 @@ fn check_binding_alt_eq_ty(
|
||||
ti: &TopInfo<'tcx>,
|
||||
) {
|
||||
let var_ty = self.local_ty(span, var_id);
|
||||
if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
|
||||
if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
|
||||
let hir = self.tcx.hir();
|
||||
let var_ty = self.resolve_vars_if_possible(var_ty);
|
||||
let msg = format!("first introduced with type `{var_ty}` here");
|
||||
@ -986,13 +987,12 @@ fn check_pat_struct(
|
||||
};
|
||||
|
||||
// Type-check the path.
|
||||
self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
|
||||
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
|
||||
pat_ty
|
||||
} else {
|
||||
Ty::new_misc_error(self.tcx)
|
||||
match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
|
||||
Ok(()) => pat_ty,
|
||||
Err(guar) => Ty::new_error(self.tcx, guar),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1050,7 +1050,7 @@ fn check_pat_path(
|
||||
// Type-check the path.
|
||||
let (pat_ty, pat_res) =
|
||||
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
|
||||
if let Some(err) =
|
||||
if let Err(err) =
|
||||
self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
|
||||
{
|
||||
self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
|
||||
@ -1223,12 +1223,7 @@ fn check_pat_tuple_struct(
|
||||
|
||||
// Type-check the tuple struct pattern against the expected type.
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
|
||||
let had_err = if let Some(err) = diag {
|
||||
err.emit();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let had_err = diag.map_err(|diag| diag.emit());
|
||||
|
||||
// Type-check subpatterns.
|
||||
if subpats.len() == variant.fields.len()
|
||||
@ -1249,6 +1244,10 @@ fn check_pat_tuple_struct(
|
||||
None,
|
||||
);
|
||||
}
|
||||
if let Err(e) = had_err {
|
||||
on_error(e);
|
||||
return Ty::new_error(tcx, e);
|
||||
}
|
||||
} else {
|
||||
let e = self.emit_err_pat_wrong_number_of_fields(
|
||||
pat.span,
|
||||
@ -1273,7 +1272,7 @@ fn emit_err_pat_wrong_number_of_fields(
|
||||
subpats: &'tcx [Pat<'tcx>],
|
||||
fields: &'tcx [ty::FieldDef],
|
||||
expected: Ty<'tcx>,
|
||||
had_err: bool,
|
||||
had_err: Result<(), ErrorGuaranteed>,
|
||||
) -> ErrorGuaranteed {
|
||||
let subpats_ending = pluralize!(subpats.len());
|
||||
let fields_ending = pluralize!(fields.len());
|
||||
@ -1330,7 +1329,7 @@ fn emit_err_pat_wrong_number_of_fields(
|
||||
// #67037: only do this if we could successfully type-check the expected type against
|
||||
// the tuple struct pattern. Otherwise the args could get out of range on e.g.,
|
||||
// `let P() = U;` where `P != U` with `struct P<T>(T);`.
|
||||
(ty::Adt(_, args), [field], false) => {
|
||||
(ty::Adt(_, args), [field], Ok(())) => {
|
||||
let field_ty = self.field_ty(pat_span, field, args);
|
||||
match field_ty.kind() {
|
||||
ty::Tuple(fields) => fields.len() == subpats.len(),
|
||||
@ -1445,8 +1444,7 @@ fn check_pat_tuple(
|
||||
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
|
||||
let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
|
||||
let pat_ty = Ty::new_tup(tcx, element_tys);
|
||||
if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
|
||||
let reported = err.emit();
|
||||
if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) {
|
||||
// Walk subpatterns with an expected type of `err` in this case to silence
|
||||
// further errors being emitted when using the bindings. #50333
|
||||
let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
|
||||
@ -1470,7 +1468,7 @@ fn check_struct_pat_fields(
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
has_rest_pat: bool,
|
||||
pat_info: PatInfo<'tcx, '_>,
|
||||
) -> bool {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let ty::Adt(adt, args) = adt_ty.kind() else {
|
||||
@ -1486,7 +1484,7 @@ fn check_struct_pat_fields(
|
||||
|
||||
// Keep track of which fields have already appeared in the pattern.
|
||||
let mut used_fields = FxHashMap::default();
|
||||
let mut no_field_errors = true;
|
||||
let mut result = Ok(());
|
||||
|
||||
let mut inexistent_fields = vec![];
|
||||
// Typecheck each field.
|
||||
@ -1495,8 +1493,8 @@ fn check_struct_pat_fields(
|
||||
let ident = tcx.adjust_ident(field.ident, variant.def_id);
|
||||
let field_ty = match used_fields.entry(ident) {
|
||||
Occupied(occupied) => {
|
||||
no_field_errors = false;
|
||||
let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
|
||||
result = Err(guar);
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
Vacant(vacant) => {
|
||||
@ -1511,7 +1509,6 @@ fn check_struct_pat_fields(
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
inexistent_fields.push(field);
|
||||
no_field_errors = false;
|
||||
Ty::new_misc_error(tcx)
|
||||
})
|
||||
}
|
||||
@ -1585,37 +1582,31 @@ fn check_struct_pat_fields(
|
||||
}
|
||||
match (inexistent_fields_err, unmentioned_err) {
|
||||
(Some(i), Some(u)) => {
|
||||
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
// We don't want to show the nonexistent fields error when this was
|
||||
// `Foo { a, b }` when it should have been `Foo(a, b)`.
|
||||
i.delay_as_bug();
|
||||
u.delay_as_bug();
|
||||
e.emit();
|
||||
Err(e)
|
||||
} else {
|
||||
i.emit();
|
||||
u.emit();
|
||||
Err(u.emit())
|
||||
}
|
||||
}
|
||||
(None, Some(u)) => {
|
||||
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
|
||||
u.delay_as_bug();
|
||||
e.emit();
|
||||
Err(e)
|
||||
} else {
|
||||
u.emit();
|
||||
Err(u.emit())
|
||||
}
|
||||
}
|
||||
(Some(err), None) => {
|
||||
err.emit();
|
||||
(Some(err), None) => Err(err.emit()),
|
||||
(None, None) => {
|
||||
self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
|
||||
result
|
||||
}
|
||||
(None, None)
|
||||
if let Some(err) =
|
||||
self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
|
||||
{
|
||||
err.emit();
|
||||
}
|
||||
(None, None) => {}
|
||||
}
|
||||
no_field_errors
|
||||
}
|
||||
|
||||
fn error_tuple_variant_index_shorthand(
|
||||
@ -1623,7 +1614,7 @@ fn error_tuple_variant_index_shorthand(
|
||||
variant: &VariantDef,
|
||||
pat: &'_ Pat<'_>,
|
||||
fields: &[hir::PatField<'_>],
|
||||
) -> Option<Diag<'_>> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
// if this is a tuple struct, then all field names will be numbers
|
||||
// so if any fields in a struct pattern use shorthand syntax, they will
|
||||
// be invalid identifiers (for example, Foo { 0, 1 }).
|
||||
@ -1645,10 +1636,10 @@ fn error_tuple_variant_index_shorthand(
|
||||
format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return Some(err);
|
||||
return Err(err.emit());
|
||||
}
|
||||
}
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
|
||||
@ -1804,14 +1795,14 @@ fn error_tuple_variant_as_struct_pat(
|
||||
pat: &Pat<'_>,
|
||||
fields: &'tcx [hir::PatField<'tcx>],
|
||||
variant: &ty::VariantDef,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
|
||||
(variant.ctor_kind(), &pat.kind)
|
||||
{
|
||||
let is_tuple_struct_match = !pattern_fields.is_empty()
|
||||
&& pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
|
||||
if is_tuple_struct_match {
|
||||
return None;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
|
||||
@ -1839,9 +1830,9 @@ fn error_tuple_variant_as_struct_pat(
|
||||
format!("({sugg})"),
|
||||
appl,
|
||||
);
|
||||
return Some(err);
|
||||
return Err(err.emit());
|
||||
}
|
||||
None
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_suggested_tuple_struct_pattern(
|
||||
@ -2065,20 +2056,20 @@ fn check_pat_box(
|
||||
pat_info: PatInfo<'tcx, '_>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
|
||||
Ok(()) => {
|
||||
let (box_ty, inner_ty) = self
|
||||
.check_dereferenceable(span, expected, inner)
|
||||
.and_then(|()| {
|
||||
// Here, `demand::subtype` is good enough, but I don't
|
||||
// think any errors can be introduced by using `demand::eqtype`.
|
||||
let inner_ty = self.next_ty_var(inner.span);
|
||||
let box_ty = Ty::new_box(tcx, inner_ty);
|
||||
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
|
||||
(box_ty, inner_ty)
|
||||
}
|
||||
Err(guar) => {
|
||||
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?;
|
||||
Ok((box_ty, inner_ty))
|
||||
})
|
||||
.unwrap_or_else(|guar| {
|
||||
let err = Ty::new_error(tcx, guar);
|
||||
(err, err)
|
||||
}
|
||||
};
|
||||
});
|
||||
self.check_pat(inner, inner_ty, pat_info);
|
||||
box_ty
|
||||
}
|
||||
@ -2222,7 +2213,7 @@ fn check_pat_ref(
|
||||
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
if let Err(mut err) = err {
|
||||
self.borrow_pat_suggestion(&mut err, pat);
|
||||
err.emit();
|
||||
}
|
||||
@ -2327,7 +2318,7 @@ fn check_pat_slice(
|
||||
self.try_resolve_slice_ty_to_array_ty(before, slice, span)
|
||||
{
|
||||
debug!(?resolved_arr_ty);
|
||||
self.demand_eqtype(span, expected, resolved_arr_ty);
|
||||
let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable)]
|
||||
pub struct MethodAutoderefStepsResult<'tcx> {
|
||||
/// The valid autoderef steps that could be find.
|
||||
/// The valid autoderef steps that could be found.
|
||||
pub steps: &'tcx [CandidateStep<'tcx>],
|
||||
/// If Some(T), a type autoderef reported an error on.
|
||||
pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
|
||||
|
@ -26,27 +26,27 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# Duplicated in dist-various-2 Dockerfile.
|
||||
# FIXME: Move to canonical triple
|
||||
ENV \
|
||||
AR_x86_64_fuchsia=x86_64-unknown-fuchsia-ar \
|
||||
CC_x86_64_fuchsia=x86_64-unknown-fuchsia-clang \
|
||||
CFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
|
||||
CXX_x86_64_fuchsia=x86_64-unknown-fuchsia-clang++ \
|
||||
CXXFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
|
||||
LDFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib"
|
||||
AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
|
||||
CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
|
||||
CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
|
||||
CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
|
||||
CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
|
||||
LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib"
|
||||
|
||||
WORKDIR /tmp
|
||||
COPY scripts/shared.sh /tmp/
|
||||
COPY scripts/build-fuchsia-toolchain.sh /tmp/
|
||||
RUN /tmp/build-fuchsia-toolchain.sh
|
||||
|
||||
ENV CARGO_TARGET_X86_64_FUCHSIA_AR /usr/local/bin/llvm-ar
|
||||
ENV CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS \
|
||||
ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_AR /usr/local/bin/llvm-ar
|
||||
ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS \
|
||||
-C panic=abort \
|
||||
-C force-unwind-tables=yes \
|
||||
-C link-arg=--sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot \
|
||||
-Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot/lib \
|
||||
-Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib
|
||||
|
||||
ENV TARGETS=x86_64-fuchsia
|
||||
ENV TARGETS=x86_64-unknown-fuchsia
|
||||
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnu
|
||||
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
|
||||
|
||||
@ -69,11 +69,11 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--llvm-libunwind=in-tree \
|
||||
--enable-extended \
|
||||
--disable-docs \
|
||||
--set target.x86_64-fuchsia.cc=/usr/local/bin/clang \
|
||||
--set target.x86_64-fuchsia.cxx=/usr/local/bin/clang++ \
|
||||
--set target.x86_64-fuchsia.ar=/usr/local/bin/llvm-ar \
|
||||
--set target.x86_64-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
|
||||
--set target.x86_64-fuchsia.linker=/usr/local/bin/ld.lld
|
||||
--set target.x86_64-unknown-fuchsia.cc=/usr/local/bin/clang \
|
||||
--set target.x86_64-unknown-fuchsia.cxx=/usr/local/bin/clang++ \
|
||||
--set target.x86_64-unknown-fuchsia.ar=/usr/local/bin/llvm-ar \
|
||||
--set target.x86_64-unknown-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
|
||||
--set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld
|
||||
ENV SCRIPT \
|
||||
python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \
|
||||
bash ../src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
|
||||
|
@ -35,7 +35,7 @@ PICK_REFS=()
|
||||
# commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in
|
||||
# addition to versions of prebuilts. It should be bumped regularly by the
|
||||
# Fuchsia team – we aim for every 1-2 months.
|
||||
INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
|
||||
INTEGRATION_SHA=737ebdd83afa47b742ca8325fad0176952fcefbd
|
||||
|
||||
checkout=fuchsia
|
||||
jiri=.jiri_root/bin/jiri
|
||||
|
@ -4,13 +4,13 @@ set -ex
|
||||
source shared.sh
|
||||
|
||||
FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64
|
||||
FUCHSIA_SDK_ID=version:20.20240412.3.1
|
||||
FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19
|
||||
FUCHSIA_SDK_ID=version:21.20240610.2.1
|
||||
FUCHSIA_SDK_SHA256=2d2d057fc3f0404197cced2200f88cbcdaaf5fbf6475955045091f8676791ce7
|
||||
FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk
|
||||
CLANG_DOWNLOAD_URL=\
|
||||
https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64
|
||||
CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02
|
||||
CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844
|
||||
CLANG_DOWNLOAD_ID=git_revision:3809e20afc68d7d03821f0ec59b928dcf9befbf4
|
||||
CLANG_DOWNLOAD_SHA256=3c2c442b61cd9e8f1b567738f6d53cffe11b3fc820e7dae87a82a0859be8f204
|
||||
|
||||
install_clang() {
|
||||
mkdir -p clang_download
|
||||
|
@ -286,7 +286,7 @@ class TestEnvironment:
|
||||
# Look up the product bundle transfer manifest.
|
||||
self.log_info("Looking up the product bundle transfer manifest...")
|
||||
product_name = "minimal." + self.triple_to_arch(self.target)
|
||||
fuchsia_version = "20.20240412.3.1"
|
||||
fuchsia_version = "21.20240610.2.1"
|
||||
|
||||
out = self.check_output(
|
||||
[
|
||||
|
@ -259,7 +259,7 @@ target | std | host | notes
|
||||
[`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD
|
||||
[`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
|
||||
`aarch64-unknown-redox` | ? | | ARM64 Redox OS
|
||||
`aarch64-uwp-windows-msvc` | ? | |
|
||||
`aarch64-uwp-windows-msvc` | ✓ | |
|
||||
`aarch64-wrs-vxworks` | ? | |
|
||||
`aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
|
||||
`aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
|
||||
@ -300,8 +300,8 @@ target | std | host | notes
|
||||
[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI]
|
||||
[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI]
|
||||
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI]
|
||||
`i686-uwp-windows-gnu` | ? | | [^x86_32-floats-return-ABI]
|
||||
`i686-uwp-windows-msvc` | ? | | [^x86_32-floats-return-ABI]
|
||||
`i686-uwp-windows-gnu` | ✓ | | [^x86_32-floats-return-ABI]
|
||||
`i686-uwp-windows-msvc` | ✓ | | [^x86_32-floats-return-ABI]
|
||||
[`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
|
||||
`i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI]
|
||||
[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? | | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
|
||||
@ -362,7 +362,7 @@ target | std | host | notes
|
||||
[`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
|
||||
[`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare Armv4T
|
||||
[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE
|
||||
`thumbv7a-pc-windows-msvc` | ? | |
|
||||
`thumbv7a-pc-windows-msvc` | ✓ | |
|
||||
`thumbv7a-uwp-windows-msvc` | ✓ | |
|
||||
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3
|
||||
[`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | | WebAssembly
|
||||
|
@ -1,8 +1,9 @@
|
||||
use regex::Regex;
|
||||
use similar::TextDiff;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::drop_bomb::DropBomb;
|
||||
use crate::fs_wrapper;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
@ -17,6 +18,7 @@ pub fn diff() -> Diff {
|
||||
pub struct Diff {
|
||||
expected: Option<String>,
|
||||
expected_name: Option<String>,
|
||||
expected_file: Option<PathBuf>,
|
||||
actual: Option<String>,
|
||||
actual_name: Option<String>,
|
||||
normalizers: Vec<(String, String)>,
|
||||
@ -30,6 +32,7 @@ pub fn new() -> Self {
|
||||
Self {
|
||||
expected: None,
|
||||
expected_name: None,
|
||||
expected_file: None,
|
||||
actual: None,
|
||||
actual_name: None,
|
||||
normalizers: Vec::new(),
|
||||
@ -40,9 +43,10 @@ pub fn new() -> Self {
|
||||
/// Specify the expected output for the diff from a file.
|
||||
pub fn expected_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
let path = path.as_ref();
|
||||
let content = std::fs::read_to_string(path).expect("failed to read file");
|
||||
let content = fs_wrapper::read_to_string(path);
|
||||
let name = path.to_string_lossy().to_string();
|
||||
|
||||
self.expected_file = Some(path.into());
|
||||
self.expected = Some(content);
|
||||
self.expected_name = Some(name);
|
||||
self
|
||||
@ -58,10 +62,7 @@ pub fn expected_text<T: AsRef<[u8]>>(&mut self, name: &str, text: T) -> &mut Sel
|
||||
/// Specify the actual output for the diff from a file.
|
||||
pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
let path = path.as_ref();
|
||||
let content = match std::fs::read_to_string(path) {
|
||||
Ok(c) => c,
|
||||
Err(e) => panic!("failed to read `{}`: {:?}", path.display(), e),
|
||||
};
|
||||
let content = fs_wrapper::read_to_string(path);
|
||||
let name = path.to_string_lossy().to_string();
|
||||
|
||||
self.actual = Some(content);
|
||||
@ -104,6 +105,15 @@ pub fn run(&mut self) {
|
||||
.to_string();
|
||||
|
||||
if !output.is_empty() {
|
||||
// If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
|
||||
// environment variable set), then we write into the file and return.
|
||||
if let Some(ref expected_file) = self.expected_file {
|
||||
if std::env::var("RUSTC_BLESS_TEST").is_ok() {
|
||||
println!("Blessing `{}`", expected_file.display());
|
||||
fs_wrapper::write(expected_file, actual);
|
||||
return;
|
||||
}
|
||||
}
|
||||
panic!(
|
||||
"test failed: `{}` is different from `{}`\n\n{}",
|
||||
expected_name, actual_name, output
|
||||
|
@ -18,7 +18,6 @@ run-make/compiler-lookup-paths-2/Makefile
|
||||
run-make/compiler-lookup-paths/Makefile
|
||||
run-make/compiler-rt-works-on-mingw/Makefile
|
||||
run-make/compressed-debuginfo/Makefile
|
||||
run-make/const_fn_mir/Makefile
|
||||
run-make/crate-hash-rustc-version/Makefile
|
||||
run-make/crate-name-priority/Makefile
|
||||
run-make/cross-lang-lto-clang/Makefile
|
||||
|
@ -1,22 +0,0 @@
|
||||
//@ known-bug: #109812
|
||||
|
||||
#![warn(rust_2021_incompatible_closure_captures)]
|
||||
|
||||
enum Either {
|
||||
One(X),
|
||||
Two(X),
|
||||
}
|
||||
|
||||
struct X(Y);
|
||||
|
||||
struct Y;
|
||||
|
||||
fn move_into_fnmut() {
|
||||
let x = X(Y);
|
||||
|
||||
consume_fnmut(|| {
|
||||
let Either::Two(ref mut _t) = x;
|
||||
|
||||
let X(mut _t) = x;
|
||||
});
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
//@ known-bug: rust-lang/rust#125914
|
||||
enum AstKind<'ast> {
|
||||
ExprInt,
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
Bar(isize),
|
||||
Baz,
|
||||
}
|
||||
|
||||
enum Other {
|
||||
Other1(Foo),
|
||||
Other2(AstKind),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match Other::Other1(Foo::Baz) {
|
||||
::Other::Other2(::Foo::Bar(..)) => {}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
# needs-unwind -Cpanic=abort gives different MIR output
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
|
||||
$(RUSTC_TEST_OP) "$(TMPDIR)"/dump.mir dump.mir
|
8
tests/run-make/const_fn_mir/rmake.rs
Normal file
8
tests/run-make/const_fn_mir/rmake.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// The `needs-unwind -Cpanic=abort` gives a different MIR output.
|
||||
|
||||
use run_make_support::{cwd, diff, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().input("main.rs").emit("mir").output("dump-actual.mir").run();
|
||||
diff().expected_file("dump.mir").actual_file("dump-actual.mir").run();
|
||||
}
|
17
tests/ui/impl-trait/call_method_ambiguous.next.stderr
Normal file
17
tests/ui/impl-trait/call_method_ambiguous.next.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/call_method_ambiguous.rs:29:13
|
||||
|
|
||||
LL | let mut iter = foo(n - 1, m);
|
||||
| ^^^^^^^^
|
||||
LL |
|
||||
LL | assert_eq!(iter.get(), 1);
|
||||
| ---- type must be known at this point
|
||||
|
|
||||
help: consider giving `iter` an explicit type
|
||||
|
|
||||
LL | let mut iter: /* Type */ = foo(n - 1, m);
|
||||
| ++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
39
tests/ui/impl-trait/call_method_ambiguous.rs
Normal file
39
tests/ui/impl-trait/call_method_ambiguous.rs
Normal file
@ -0,0 +1,39 @@
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] run-pass
|
||||
|
||||
#![feature(precise_capturing)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Get {
|
||||
fn get(&mut self) -> u32;
|
||||
}
|
||||
|
||||
impl Get for () {
|
||||
fn get(&mut self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Get for &mut T
|
||||
where
|
||||
T: Get,
|
||||
{
|
||||
fn get(&mut self) -> u32 {
|
||||
T::get(self) + 1
|
||||
}
|
||||
}
|
||||
|
||||
fn foo(n: usize, m: &mut ()) -> impl use<'_> Get {
|
||||
if n > 0 {
|
||||
let mut iter = foo(n - 1, m);
|
||||
//[next]~^ type annotations needed
|
||||
assert_eq!(iter.get(), 1);
|
||||
}
|
||||
m
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let g = foo(1, &mut ()).get();
|
||||
assert_eq!(g, 1);
|
||||
}
|
17
tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
Normal file
17
tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/call_method_on_inherent_impl.rs:18:13
|
||||
|
|
||||
LL | let x = my_foo();
|
||||
| ^
|
||||
LL |
|
||||
LL | x.my_debug();
|
||||
| - type must be known at this point
|
||||
|
|
||||
help: consider giving `x` an explicit type
|
||||
|
|
||||
LL | let x: /* Type */ = my_foo();
|
||||
| ++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
25
tests/ui/impl-trait/call_method_on_inherent_impl.rs
Normal file
25
tests/ui/impl-trait/call_method_on_inherent_impl.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] check-pass
|
||||
|
||||
trait MyDebug {
|
||||
fn my_debug(&self);
|
||||
}
|
||||
|
||||
impl<T> MyDebug for T
|
||||
where
|
||||
T: std::fmt::Debug,
|
||||
{
|
||||
fn my_debug(&self) {}
|
||||
}
|
||||
|
||||
fn my_foo() -> impl std::fmt::Debug {
|
||||
if false {
|
||||
let x = my_foo();
|
||||
//[next]~^ type annotations needed
|
||||
x.my_debug();
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,16 @@
|
||||
error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope
|
||||
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11
|
||||
|
|
||||
LL | x.my_debug();
|
||||
| ^^^^^^^^ method not found in `&impl Debug`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
|
||||
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:4:1
|
||||
|
|
||||
LL | trait MyDebug {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -0,0 +1,17 @@
|
||||
error[E0282]: type annotations needed for `&_`
|
||||
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13
|
||||
|
|
||||
LL | let x = &my_foo();
|
||||
| ^
|
||||
LL |
|
||||
LL | x.my_debug();
|
||||
| -------- type must be known at this point
|
||||
|
|
||||
help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let x: &_ = &my_foo();
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
@ -0,0 +1,22 @@
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
trait MyDebug {
|
||||
fn my_debug(&self);
|
||||
}
|
||||
|
||||
impl MyDebug for &() {
|
||||
fn my_debug(&self) {}
|
||||
}
|
||||
|
||||
fn my_foo() -> impl std::fmt::Debug {
|
||||
if false {
|
||||
let x = &my_foo();
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
x.my_debug();
|
||||
//[current]~^ ERROR: no method named `my_debug`
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,40 @@
|
||||
error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:20:11
|
||||
|
|
||||
LL | fn my_debug(&self);
|
||||
| -------- the method is available for `&impl Debug` here
|
||||
...
|
||||
LL | x.my_debug();
|
||||
| ^^^^^^^^ method not found in `impl Debug`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:4:1
|
||||
|
|
||||
LL | trait MyDebug {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0391]: cycle detected when computing type of opaque `my_foo::{opaque#0}`
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:15:16
|
||||
|
|
||||
LL | fn my_foo() -> impl std::fmt::Debug {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires type-checking `my_foo`...
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:20:9
|
||||
|
|
||||
LL | x.my_debug();
|
||||
| ^
|
||||
= note: ...which requires evaluating trait selection obligation `my_foo::{opaque#0}: core::marker::Unpin`...
|
||||
= note: ...which again requires computing type of opaque `my_foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when computing type of `my_foo::{opaque#0}`
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:15:16
|
||||
|
|
||||
LL | fn my_foo() -> impl std::fmt::Debug {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0391, E0599.
|
||||
For more information about an error, try `rustc --explain E0391`.
|
@ -0,0 +1,31 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:18:13
|
||||
|
|
||||
LL | let x = my_foo();
|
||||
| ^
|
||||
LL |
|
||||
LL | x.my_debug();
|
||||
| - type must be known at this point
|
||||
|
|
||||
help: consider giving `x` an explicit type
|
||||
|
|
||||
LL | let x: /* Type */ = my_foo();
|
||||
| ++++++++++++
|
||||
|
||||
error[E0282]: type annotations needed for `&_`
|
||||
--> $DIR/call_method_on_inherent_impl_ref.rs:28:13
|
||||
|
|
||||
LL | let x = &my_bar();
|
||||
| ^
|
||||
LL |
|
||||
LL | x.my_debug();
|
||||
| -------- type must be known at this point
|
||||
|
|
||||
help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let x: &_ = &my_bar();
|
||||
| ++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
35
tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
Normal file
35
tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
Normal file
@ -0,0 +1,35 @@
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
trait MyDebug {
|
||||
fn my_debug(&self);
|
||||
}
|
||||
|
||||
impl<T> MyDebug for &T
|
||||
where
|
||||
T: std::fmt::Debug,
|
||||
{
|
||||
fn my_debug(&self) {}
|
||||
}
|
||||
|
||||
fn my_foo() -> impl std::fmt::Debug {
|
||||
//[current]~^ cycle
|
||||
if false {
|
||||
let x = my_foo();
|
||||
//[next]~^ type annotations needed
|
||||
x.my_debug();
|
||||
//[current]~^ no method named `my_debug` found
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
fn my_bar() -> impl std::fmt::Debug {
|
||||
if false {
|
||||
let x = &my_bar();
|
||||
//[next]~^ type annotations needed
|
||||
x.my_debug();
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,37 @@
|
||||
error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the current scope
|
||||
--> $DIR/call_method_without_import.rs:17:11
|
||||
|
|
||||
LL | x.fmt(f);
|
||||
| ^^^ method not found in `impl Debug`
|
||||
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
||||
|
|
||||
= note: the method is available for `impl Debug` here
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: trait `Debug` which provides `fmt` is implemented but not in scope; perhaps you want to import it
|
||||
|
|
||||
LL + use std::fmt::Debug;
|
||||
|
|
||||
|
||||
error[E0599]: no method named `fmt` found for mutable reference `&mut impl Debug` in the current scope
|
||||
--> $DIR/call_method_without_import.rs:26:11
|
||||
|
|
||||
LL | x.fmt(f);
|
||||
| ^^^ method not found in `&mut impl Debug`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is in scope
|
||||
help: the following traits which provide `fmt` are implemented but not in scope; perhaps you want to import one of them
|
||||
|
|
||||
LL + use std::fmt::Binary;
|
||||
|
|
||||
LL + use std::fmt::Debug;
|
||||
|
|
||||
LL + use std::fmt::Display;
|
||||
|
|
||||
LL + use std::fmt::LowerExp;
|
||||
|
|
||||
and 5 other candidates
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
42
tests/ui/impl-trait/call_method_without_import.rs
Normal file
42
tests/ui/impl-trait/call_method_without_import.rs
Normal file
@ -0,0 +1,42 @@
|
||||
//! Test that opaque types only pick up methods from traits in their bounds
|
||||
//! if the trait is imported.
|
||||
//!
|
||||
//! FIXME: always look through the bounds of an opaque type to see if there are
|
||||
//! methods that could be called on any of the bound traits, irrespective of
|
||||
//! imported traits.
|
||||
|
||||
//@ revisions: import no_import
|
||||
//@[import] check-pass
|
||||
|
||||
#[cfg(import)]
|
||||
use std::fmt::Debug as _;
|
||||
|
||||
fn foo(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
|
||||
if false {
|
||||
let x = foo(f);
|
||||
x.fmt(f);
|
||||
//[no_import]~^ ERROR: no method named `fmt` found
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
fn foo1(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
|
||||
if false {
|
||||
let x = &mut foo(f);
|
||||
x.fmt(f);
|
||||
//[no_import]~^ ERROR: no method named `fmt` found
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
// inconsistent with this
|
||||
fn bar<T>(t: impl std::fmt::Debug, f: &mut std::fmt::Formatter<'_>) {
|
||||
t.fmt(f);
|
||||
}
|
||||
|
||||
// and the desugared version, of course
|
||||
fn baz<T: std::fmt::Debug>(t: T, f: &mut std::fmt::Formatter<'_>) {
|
||||
t.fmt(f);
|
||||
}
|
||||
|
||||
fn main() {}
|
26
tests/ui/impl-trait/method-resolution.rs
Normal file
26
tests/ui/impl-trait/method-resolution.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//! Since there is only one possible `bar` method, we invoke it and subsequently
|
||||
//! constrain `foo`'s RPIT to `u32`.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl Trait for u32 {}
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<u32> {
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
fn foo(x: bool) -> Bar<impl Sized> {
|
||||
if x {
|
||||
let x = foo(false);
|
||||
x.bar();
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
20
tests/ui/impl-trait/method-resolution2.next.stderr
Normal file
20
tests/ui/impl-trait/method-resolution2.next.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/method-resolution2.rs:25:11
|
||||
|
|
||||
LL | x.bar();
|
||||
| ^^^ multiple `bar` found
|
||||
|
|
||||
note: candidate #1 is defined in an impl for the type `Bar<T>`
|
||||
--> $DIR/method-resolution2.rs:19:5
|
||||
|
|
||||
LL | fn bar(self) {}
|
||||
| ^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl for the type `Bar<u32>`
|
||||
--> $DIR/method-resolution2.rs:15:5
|
||||
|
|
||||
LL | fn bar(self) {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
31
tests/ui/impl-trait/method-resolution2.rs
Normal file
31
tests/ui/impl-trait/method-resolution2.rs
Normal file
@ -0,0 +1,31 @@
|
||||
//! Check that the method call does not constrain the RPIT to `i32`, even though
|
||||
//! `i32` is the only type that satisfies the RPIT's trait bounds.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] check-pass
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl Trait for i32 {}
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<u32> {
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
impl<T: Trait> Bar<T> {
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
fn foo(x: bool) -> Bar<impl Trait> {
|
||||
if x {
|
||||
let x = foo(false);
|
||||
x.bar();
|
||||
//[next]~^ ERROR: multiple applicable items in scope
|
||||
}
|
||||
Bar(42_i32)
|
||||
}
|
||||
|
||||
fn main() {}
|
20
tests/ui/impl-trait/method-resolution3.current.stderr
Normal file
20
tests/ui/impl-trait/method-resolution3.current.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/method-resolution3.rs:21:11
|
||||
|
|
||||
LL | x.bar();
|
||||
| ^^^ multiple `bar` found
|
||||
|
|
||||
note: candidate #1 is defined in an impl for the type `Bar<i32>`
|
||||
--> $DIR/method-resolution3.rs:15:5
|
||||
|
|
||||
LL | fn bar(self) {}
|
||||
| ^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl for the type `Bar<u32>`
|
||||
--> $DIR/method-resolution3.rs:11:5
|
||||
|
|
||||
LL | fn bar(self) {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
20
tests/ui/impl-trait/method-resolution3.next.stderr
Normal file
20
tests/ui/impl-trait/method-resolution3.next.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0034]: multiple applicable items in scope
|
||||
--> $DIR/method-resolution3.rs:21:11
|
||||
|
|
||||
LL | x.bar();
|
||||
| ^^^ multiple `bar` found
|
||||
|
|
||||
note: candidate #1 is defined in an impl for the type `Bar<i32>`
|
||||
--> $DIR/method-resolution3.rs:15:5
|
||||
|
|
||||
LL | fn bar(self) {}
|
||||
| ^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl for the type `Bar<u32>`
|
||||
--> $DIR/method-resolution3.rs:11:5
|
||||
|
|
||||
LL | fn bar(self) {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0034`.
|
27
tests/ui/impl-trait/method-resolution3.rs
Normal file
27
tests/ui/impl-trait/method-resolution3.rs
Normal file
@ -0,0 +1,27 @@
|
||||
//! Check that we consider `Bar<impl Sized>` to successfully unify
|
||||
//! with both `Bar<u32>` and `Bar<i32>` (in isolation), so we bail
|
||||
//! out with ambiguity.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<u32> {
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
impl Bar<i32> {
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
fn foo(x: bool) -> Bar<impl Sized> {
|
||||
if x {
|
||||
let x = foo(false);
|
||||
x.bar();
|
||||
//~^ ERROR: multiple applicable items in scope
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
22
tests/ui/impl-trait/method-resolution4.next.stderr
Normal file
22
tests/ui/impl-trait/method-resolution4.next.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/method-resolution4.rs:13:9
|
||||
|
|
||||
LL | foo(false).next().unwrap();
|
||||
| ^^^^^^^^^^ cannot infer type
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/method-resolution4.rs:16:5
|
||||
|
|
||||
LL | fn foo(b: bool) -> impl Iterator<Item = ()> {
|
||||
| ------------------------ the expected opaque type
|
||||
...
|
||||
LL | std::iter::empty()
|
||||
| ^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected opaque type `impl Iterator<Item = ()>`
|
||||
found struct `std::iter::Empty<_>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0308.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
20
tests/ui/impl-trait/method-resolution4.rs
Normal file
20
tests/ui/impl-trait/method-resolution4.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! The recursive method call yields the opaque type. The
|
||||
//! `next` method call then constrains the hidden type to `&mut _`
|
||||
//! because `next` takes `&mut self`. We never resolve the inference
|
||||
//! variable, but get a type mismatch when comparing `&mut _` with
|
||||
//! `std::iter::Empty`.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] check-pass
|
||||
|
||||
fn foo(b: bool) -> impl Iterator<Item = ()> {
|
||||
if b {
|
||||
foo(false).next().unwrap();
|
||||
//[next]~^ type annotations needed
|
||||
}
|
||||
std::iter::empty()
|
||||
//[next]~^ mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
42
tests/ui/impl-trait/recursive-parent-trait-method-call.rs
Normal file
42
tests/ui/impl-trait/recursive-parent-trait-method-call.rs
Normal file
@ -0,0 +1,42 @@
|
||||
//! This test checks that we can resolve the `boxed` method call to `FutureExt`,
|
||||
//! because we know that the anonymous future does not implement `StreamExt`.
|
||||
|
||||
//@ edition: 2021
|
||||
//@ check-pass
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
trait FutureExt: Future + Sized + Send + 'static {
|
||||
fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
|
||||
Box::pin(self)
|
||||
}
|
||||
}
|
||||
|
||||
trait StreamExt: Future + Sized + Send + 'static {
|
||||
fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
|
||||
Box::pin(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Future + Sized + Send + 'static> FutureExt for T {}
|
||||
|
||||
fn go(i: usize) -> impl Future<Output = ()> + Send + 'static {
|
||||
async move {
|
||||
if i != 0 {
|
||||
spawn(async move {
|
||||
let fut = go(i - 1).boxed();
|
||||
fut.await;
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn<T: Send>(
|
||||
_: impl Future<Output = T> + Send + 'static,
|
||||
) -> impl Future<Output = ()> + Send + 'static {
|
||||
async move { todo!() }
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,4 +1,7 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
//@ check-pass
|
||||
|
||||
struct Foo<T>(T);
|
||||
|
||||
impl Foo<u32> {
|
||||
@ -15,14 +18,11 @@ fn bar() -> Bar {
|
||||
impl Foo<Bar> {
|
||||
fn foo() -> Bar {
|
||||
Self::method();
|
||||
//~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
|
||||
Foo::<Bar>::method();
|
||||
//~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
|
||||
let x = Foo(bar());
|
||||
Foo::method2(x);
|
||||
let x = Self(bar());
|
||||
Self::method2(x);
|
||||
//~^ ERROR: no function or associated item named `method2` found for struct `Foo<Bar>`
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
|
||||
--> $DIR/opaque_param_in_ufc.rs:17:15
|
||||
|
|
||||
LL | struct Foo<T>(T);
|
||||
| ------------- function or associated item `method` not found for this struct
|
||||
...
|
||||
LL | Self::method();
|
||||
| ^^^^^^ function or associated item not found in `Foo<Bar>`
|
||||
|
|
||||
= note: the function or associated item was found for
|
||||
- `Foo<u32>`
|
||||
|
||||
error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
|
||||
--> $DIR/opaque_param_in_ufc.rs:19:21
|
||||
|
|
||||
LL | struct Foo<T>(T);
|
||||
| ------------- function or associated item `method` not found for this struct
|
||||
...
|
||||
LL | Foo::<Bar>::method();
|
||||
| ^^^^^^ function or associated item not found in `Foo<Bar>`
|
||||
|
|
||||
= note: the function or associated item was found for
|
||||
- `Foo<u32>`
|
||||
|
||||
error[E0599]: no function or associated item named `method2` found for struct `Foo<Bar>` in the current scope
|
||||
--> $DIR/opaque_param_in_ufc.rs:24:15
|
||||
|
|
||||
LL | struct Foo<T>(T);
|
||||
| ------------- function or associated item `method2` not found for this struct
|
||||
...
|
||||
LL | Self::method2(x);
|
||||
| ^^^^^^^ function or associated item not found in `Foo<Bar>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -1,10 +1,11 @@
|
||||
//@ known-bug: #124004
|
||||
//! This test used to ICE #124004
|
||||
|
||||
#![feature(box_patterns)]
|
||||
|
||||
use std::ops::{ Deref };
|
||||
|
||||
struct X(dyn Iterator<Item = &'a ()>);
|
||||
//~^ ERROR: use of undeclared lifetime name `'a`
|
||||
|
||||
impl Deref for X {
|
||||
type Target = isize;
|
19
tests/ui/pattern/box-pattern-type-mismatch.stderr
Normal file
19
tests/ui/pattern/box-pattern-type-mismatch.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/box-pattern-type-mismatch.rs:7:31
|
||||
|
|
||||
LL | struct X(dyn Iterator<Item = &'a ()>);
|
||||
| ^^ 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 `'a` lifetime
|
||||
|
|
||||
LL | struct X(dyn for<'a> Iterator<Item = &'a ()>);
|
||||
| +++++++
|
||||
help: consider introducing lifetime `'a` here
|
||||
|
|
||||
LL | struct X<'a>(dyn Iterator<Item = &'a ()>);
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0261`.
|
25
tests/ui/pattern/missing_lifetime.rs
Normal file
25
tests/ui/pattern/missing_lifetime.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! This test used to ICE: rust-lang/rust#125914
|
||||
//! Instead of actually analyzing the erroneous patterns,
|
||||
//! we instead stop after typeck where errors are already
|
||||
//! reported.
|
||||
|
||||
enum AstKind<'ast> {
|
||||
//~^ ERROR: `'ast` is never used
|
||||
ExprInt,
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
Bar(isize),
|
||||
Baz,
|
||||
}
|
||||
|
||||
enum Other {
|
||||
Other1(Foo),
|
||||
Other2(AstKind), //~ ERROR: missing lifetime specifier
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match Other::Other1(Foo::Baz) {
|
||||
::Other::Other2(::Foo::Bar(..)) => {}
|
||||
}
|
||||
}
|
25
tests/ui/pattern/missing_lifetime.stderr
Normal file
25
tests/ui/pattern/missing_lifetime.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing_lifetime.rs:18:12
|
||||
|
|
||||
LL | Other2(AstKind),
|
||||
| ^^^^^^^ expected named lifetime parameter
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL ~ enum Other<'a> {
|
||||
LL | Other1(Foo),
|
||||
LL ~ Other2(AstKind<'a>),
|
||||
|
|
||||
|
||||
error[E0392]: lifetime parameter `'ast` is never used
|
||||
--> $DIR/missing_lifetime.rs:6:14
|
||||
|
|
||||
LL | enum AstKind<'ast> {
|
||||
| ^^^^ unused lifetime parameter
|
||||
|
|
||||
= help: consider removing `'ast`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0106, E0392.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
30
tests/ui/pattern/type_mismatch.rs
Normal file
30
tests/ui/pattern/type_mismatch.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! This test used to ICE: rust-lang/rust#109812
|
||||
//! Instead of actually analyzing the erroneous patterns,
|
||||
//! we instead stop after typeck where errors are already
|
||||
//! reported.
|
||||
|
||||
#![warn(rust_2021_incompatible_closure_captures)]
|
||||
|
||||
enum Either {
|
||||
One(X),
|
||||
Two(X),
|
||||
}
|
||||
|
||||
struct X(Y);
|
||||
|
||||
struct Y;
|
||||
|
||||
fn consume_fnmut(_: impl FnMut()) {}
|
||||
|
||||
fn move_into_fnmut() {
|
||||
let x = X(Y);
|
||||
|
||||
consume_fnmut(|| {
|
||||
let Either::Two(ref mut _t) = x;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
let X(mut _t) = x;
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {}
|
11
tests/ui/pattern/type_mismatch.stderr
Normal file
11
tests/ui/pattern/type_mismatch.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:23:13
|
||||
|
|
||||
LL | let Either::Two(ref mut _t) = x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `X`
|
||||
| |
|
||||
| expected `X`, found `Either`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -0,0 +1,15 @@
|
||||
error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
|
||||
--> $DIR/method_resolution.rs:21:14
|
||||
|
|
||||
LL | struct Bar<T>(T);
|
||||
| ------------- method `bar` not found for this struct
|
||||
...
|
||||
LL | self.bar()
|
||||
| ^^^ method not found in `Bar<u32>`
|
||||
|
|
||||
= note: the method was found for
|
||||
- `Bar<Foo>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
12
tests/ui/type-alias-impl-trait/method_resolution.next.stderr
Normal file
12
tests/ui/type-alias-impl-trait/method_resolution.next.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
|
||||
--> $DIR/method_resolution.rs:21:14
|
||||
|
|
||||
LL | struct Bar<T>(T);
|
||||
| ------------- method `bar` not found for this struct
|
||||
...
|
||||
LL | self.bar()
|
||||
| ^^^ method cannot be called on `Bar<u32>` due to unsatisfied trait bounds
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
30
tests/ui/type-alias-impl-trait/method_resolution.rs
Normal file
30
tests/ui/type-alias-impl-trait/method_resolution.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! `Bar<u32>::foo` is not defining `Foo`, so it cannot rely on the fact that
|
||||
//! `u32` is the hidden type of `Foo` to call `bar`
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl Sized;
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<Foo> {
|
||||
fn bar(mut self) {
|
||||
self.0 = 42_u32;
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar<u32> {
|
||||
fn foo(self) {
|
||||
self.bar()
|
||||
//~^ ERROR: no method named `bar`
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
42_u32
|
||||
}
|
||||
|
||||
fn main() {}
|
28
tests/ui/type-alias-impl-trait/method_resolution2.rs
Normal file
28
tests/ui/type-alias-impl-trait/method_resolution2.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//! Check that we do unify `Bar<Foo>` with `Bar<u32>`, as the
|
||||
//! `foo` method call can be resolved unambiguously by doing so.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl Sized;
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<Foo> {
|
||||
fn bar(self) {
|
||||
self.foo()
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar<u32> {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
42_u32
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,21 @@
|
||||
error[E0307]: invalid `self` parameter type: `Bar<u32>`
|
||||
--> $DIR/method_resolution3.rs:16:18
|
||||
|
|
||||
LL | fn bar(self: Bar<u32>) {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must be `Self` or a type that dereferences to it
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0307]: invalid `self` parameter type: `&Bar<u32>`
|
||||
--> $DIR/method_resolution3.rs:21:18
|
||||
|
|
||||
LL | fn baz(self: &Bar<u32>) {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must be `Self` or a type that dereferences to it
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0307`.
|
@ -0,0 +1,15 @@
|
||||
error[E0271]: type mismatch resolving `Foo == u32`
|
||||
--> $DIR/method_resolution3.rs:16:18
|
||||
|
|
||||
LL | fn bar(self: Bar<u32>) {
|
||||
| ^^^^^^^^ types differ
|
||||
|
||||
error[E0271]: type mismatch resolving `Foo == u32`
|
||||
--> $DIR/method_resolution3.rs:21:18
|
||||
|
|
||||
LL | fn baz(self: &Bar<u32>) {
|
||||
| ^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
36
tests/ui/type-alias-impl-trait/method_resolution3.rs
Normal file
36
tests/ui/type-alias-impl-trait/method_resolution3.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//! Check that one cannot use arbitrary self types where a generic parameter
|
||||
//! mismatches with an opaque type. In theory this could unify with the opaque
|
||||
//! type, registering the generic parameter as the hidden type of the opaque type.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait, arbitrary_self_types)]
|
||||
|
||||
type Foo = impl Copy;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<Foo> {
|
||||
fn bar(self: Bar<u32>) {
|
||||
//[current]~^ ERROR: invalid `self` parameter
|
||||
//[next]~^^ ERROR: type mismatch resolving `Foo == u32`
|
||||
self.foo()
|
||||
}
|
||||
fn baz(self: &Bar<u32>) {
|
||||
//[current]~^ ERROR: invalid `self` parameter
|
||||
//[next]~^^ ERROR: type mismatch resolving `Foo == u32`
|
||||
self.foo()
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar<u32> {
|
||||
fn foo(self) {}
|
||||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
42_u32
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,21 @@
|
||||
error[E0307]: invalid `self` parameter type: `Bar<Foo>`
|
||||
--> $DIR/method_resolution4.rs:27:18
|
||||
|
|
||||
LL | fn foo(self: Bar<Foo>) {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must be `Self` or a type that dereferences to it
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
|
||||
--> $DIR/method_resolution4.rs:32:20
|
||||
|
|
||||
LL | fn foomp(self: &Bar<Foo>) {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: type of `self` must be `Self` or a type that dereferences to it
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0307`.
|
@ -0,0 +1,15 @@
|
||||
error[E0271]: type mismatch resolving `u32 == Foo`
|
||||
--> $DIR/method_resolution4.rs:27:18
|
||||
|
|
||||
LL | fn foo(self: Bar<Foo>) {
|
||||
| ^^^^^^^^ types differ
|
||||
|
||||
error[E0271]: type mismatch resolving `u32 == Foo`
|
||||
--> $DIR/method_resolution4.rs:32:20
|
||||
|
|
||||
LL | fn foomp(self: &Bar<Foo>) {
|
||||
| ^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
39
tests/ui/type-alias-impl-trait/method_resolution4.rs
Normal file
39
tests/ui/type-alias-impl-trait/method_resolution4.rs
Normal file
@ -0,0 +1,39 @@
|
||||
//! Check that one cannot use arbitrary self types where a generic parameter
|
||||
//! mismatches with an opaque type. In theory this could unify with the opaque
|
||||
//! type, registering the generic parameter as the hidden type of the opaque type.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait, arbitrary_self_types)]
|
||||
|
||||
mod foo {
|
||||
pub type Foo = impl Copy;
|
||||
|
||||
fn foo() -> Foo {
|
||||
42_u32
|
||||
}
|
||||
}
|
||||
use foo::Foo;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<Foo> {
|
||||
fn bar(self) {}
|
||||
}
|
||||
|
||||
impl Bar<u32> {
|
||||
fn foo(self: Bar<Foo>) {
|
||||
//[current]~^ ERROR: invalid `self` parameter
|
||||
//[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
|
||||
self.bar()
|
||||
}
|
||||
fn foomp(self: &Bar<Foo>) {
|
||||
//[current]~^ ERROR: invalid `self` parameter
|
||||
//[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
|
||||
self.bar()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
33
tests/ui/type-alias-impl-trait/method_resolution5.rs
Normal file
33
tests/ui/type-alias-impl-trait/method_resolution5.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! Even though `Bar<u32>::foo` is defining `Foo`, the old solver does
|
||||
//! not figure out that `u32` is the hidden type of `Foo` to call `bar`.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl Sized;
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl Bar<Foo> {
|
||||
fn bar(mut self) {
|
||||
self.0 = 42_u32;
|
||||
}
|
||||
}
|
||||
|
||||
impl Bar<u32> {
|
||||
fn foo(self)
|
||||
where
|
||||
Foo:,
|
||||
{
|
||||
self.bar()
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
42_u32
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,15 @@
|
||||
error: item does not constrain `Tait::{opaque#0}`, but has it in its signature
|
||||
--> $DIR/method_resolution_trait_method_from_opaque.rs:24:8
|
||||
|
|
||||
LL | fn foo(&mut self) {
|
||||
| ^^^
|
||||
|
|
||||
= note: consider moving the opaque type's declaration and defining uses into a separate module
|
||||
note: this opaque type is in the signature
|
||||
--> $DIR/method_resolution_trait_method_from_opaque.rs:17:13
|
||||
|
|
||||
LL | type Tait = impl Iterator<Item = ()>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -0,0 +1,9 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/method_resolution_trait_method_from_opaque.rs:26:9
|
||||
|
|
||||
LL | self.bar.next().unwrap();
|
||||
| ^^^^^^^^ cannot infer type
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
@ -0,0 +1,31 @@
|
||||
//! This test demonstrates how method calls will attempt to unify an opaque type with a reference
|
||||
//! if the method takes `&self` as its argument. This is almost never what is desired, as the user
|
||||
//! would like to have method resolution happen on the opaque type instead of inferring the hidden
|
||||
//! type. Once type-alias-impl-trait requires annotating which functions should constrain the hidden
|
||||
//! type, this won't be as much of a problem, as most functions that do method calls on opaque types
|
||||
//! won't also be the ones defining the hidden type.
|
||||
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
pub struct Foo {
|
||||
bar: Tait,
|
||||
}
|
||||
|
||||
type Tait = impl Iterator<Item = ()>;
|
||||
|
||||
impl Foo {
|
||||
pub fn new() -> Foo {
|
||||
Foo { bar: std::iter::empty() }
|
||||
}
|
||||
|
||||
fn foo(&mut self) {
|
||||
//[current]~^ ERROR: item does not constrain
|
||||
self.bar.next().unwrap();
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user