Check associated type satisfy their bounds

This was currently only happening due to eager normalization, which
isn't possible if there's specialization or bound variables.
This commit is contained in:
Matthew Jasper 2020-05-30 17:21:25 +01:00
parent 04e589ced8
commit d660dbc630
21 changed files with 625 additions and 6 deletions

View File

@ -4,15 +4,17 @@
use rustc_hir::intravisit;
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
use rustc_middle::ty;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use super::{potentially_plural_count, FnCtxt, Inherited};
use std::iter;
/// Checks that a method from an impl conforms to the signature of
/// the same method as declared in the trait.
@ -1057,13 +1059,15 @@ fn nested_visit_map(
let _: Result<(), ErrorReported> = (|| {
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
})();
}
/// The equivalent of [compare_predicate_entailment], but for associated types
/// instead of associated functions.
fn compare_type_predicate_entailment(
fn compare_type_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
@ -1165,6 +1169,152 @@ fn compare_type_predicate_entailment(
})
}
/// Validate that `ProjectionCandidate`s created for this associated type will
/// be valid.
///
/// Usually given
///
/// trait X { type Y: Copy } impl X for T { type Y = S; }
///
/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
/// impl is well-formed we have to prove `S: Copy`.
///
/// For default associated types the normalization is not possible (the value
/// from the impl could be overridden). We also can't normalize generic
/// associated types (yet) because they contain bound parameters.
fn compare_projection_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ty: &ty::AssocItem,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorReported> {
let is_gat = !tcx.generics_of(impl_ty.def_id).params.is_empty();
if impl_ty.defaultness.is_final() && !is_gat {
// For "final", non-generic associate type implementations, we
// don't need this as described above.
return Ok(());
}
let param_env = tcx.param_env(impl_ty.def_id);
let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.container.id());
let impl_ty_value = tcx.type_of(impl_ty.def_id);
// Map the predicate from the trait to the corresponding one for the impl.
// For example:
//
// trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
// impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
//
// For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
// function would translate and partially normalize
// `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
let normalized_self = if !is_gat {
// projection_predicates only includes projections where the
// substs of the trait ref are exactly the trait's identity
// substs, so we can simply return the value from the impl.
impl_ty_value
} else {
let predicate_self_ty = predicate_substs.type_at(0);
let impl_ty_substs = if let ty::Projection(p) = predicate_self_ty.kind {
assert!(
p.item_def_id == trait_ty.def_id,
"projection_predicates returned predicate for the wrong type: {}",
predicate_self_ty,
);
p.substs.rebase_onto(tcx, impl_trait_ref.def_id, impl_substs)
} else {
bug!(
"projection_predicates returned predicate for the wrong type `{}`",
predicate_self_ty,
);
};
impl_ty_value.subst(tcx, impl_ty_substs)
};
tcx.mk_substs(
iter::once(normalized_self.into())
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, impl_trait_ref.substs))),
)
};
tcx.infer_ctxt().enter(move |infcx| {
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
let infcx = &inh.infcx;
let mut selcx = traits::SelectionContext::new(&infcx);
let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
let cause = ObligationCause::new(
impl_ty_span,
impl_ty_hir_id,
ObligationCauseCode::ItemObligation(trait_ty.def_id),
);
let predicates = tcx.projection_predicates(trait_ty.def_id);
debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
for predicate in predicates {
let concrete_ty_predicate = match predicate.kind() {
ty::PredicateKind::Trait(poly_tr, c) => poly_tr
.map_bound(|tr| {
let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
})
.with_constness(*c)
.to_predicate(tcx),
ty::PredicateKind::Projection(poly_projection) => poly_projection
.map_bound(|projection| {
let projection_substs =
translate_predicate_substs(projection.projection_ty.substs);
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
substs: projection_substs,
item_def_id: projection.projection_ty.item_def_id,
},
ty: projection.ty.subst(tcx, impl_trait_ref.substs),
}
})
.to_predicate(tcx),
_ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
};
let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
&mut selcx,
param_env,
normalize_cause.clone(),
&concrete_ty_predicate,
);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
inh.register_predicates(obligations);
inh.register_predicate(traits::Obligation::new(
cause.clone(),
param_env,
normalized_predicate,
));
}
// Check that all obligations are satisfied by the implementation's
// version.
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
infcx.report_fulfillment_errors(errors, None, false);
return Err(ErrorReported);
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
Ok(())
})
}
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
match impl_item.kind {
ty::AssocKind::Const => "const",

View File

@ -0,0 +1,32 @@
// Regression test for #68641
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait UnsafeCopy {
type Item<'a>: Copy;
fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> {
*item
}
}
impl<T> UnsafeCopy for T {
type Item<'a> = T;
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
}
fn main() {
let mut s = String::from("Hello world!");
let copy = String::copy(&s);
// Do we indeed point to the samme memory?
assert!(s.as_ptr() == copy.as_ptr());
// Any use of `copy` is certeinly UB after this
drop(s);
// UB UB UB UB UB!!
println!("{}", copy);
}

View File

@ -0,0 +1,26 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68641-check-gat-bounds.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/issue-68641-check-gat-bounds.rs:15:5
|
LL | trait UnsafeCopy {
| ---------------- required by `UnsafeCopy`
...
LL | type Item<'a> = T;
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | impl<T: std::marker::Copy> UnsafeCopy for T {
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68642
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
fn main() {
<fn() -> usize>::callme(|| 1);
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68642-broken-llvm-ir.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68642-broken-llvm-ir.rs:15:5
|
LL | trait Fun {
| --------- required by `Fun`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68643
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
pub fn main() {
<fn()>::callme(|| {});
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68643-broken-mir.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68643-broken-mir.rs:15:5
|
LL | trait Fun {
| --------- required by `Fun`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68644
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
fn main() {
<u8>::callme(0);
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68644-codegen-selection.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68644-codegen-selection.rs:15:5
|
LL | trait Fun {
| --------- required by `Fun`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68645
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
fn main() {
<&dyn Iterator<Item = u8>>::callme(&std::iter::once(1));
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68645-codegen-fulfillment.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68645-codegen-fulfillment.rs:15:5
|
LL | trait Fun {
| --------- required by `Fun`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,22 @@
// Regression test for #68656
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait UnsafeCopy<T: Copy> {
type Item<'a>: std::ops::Deref<Target = T>;
fn bug<'a>(item: &Self::Item<'a>) -> () {
let x: T = **item;
&x as *const _;
}
}
impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
type Item<'a> = T;
//~^ ERROR type mismatch resolving `<T as std::ops::Deref>::Target == T`
}
fn main() {
<&'static str>::bug(&"");
}

View File

@ -0,0 +1,30 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68656-unsized-values.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0271]: type mismatch resolving `<T as std::ops::Deref>::Target == T`
--> $DIR/issue-68656-unsized-values.rs:16:5
|
LL | trait UnsafeCopy<T: Copy> {
| ------------------------- required by `UnsafeCopy`
...
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
| - this type parameter
LL | type Item<'a> = T;
| ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
|
= note: expected type parameter `T`
found associated type `<T as std::ops::Deref>::Target`
help: consider further restricting this bound
|
LL | impl<T: Copy + std::ops::Deref + std::ops::Deref<Target = T>> UnsafeCopy<T> for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0271`.

View File

@ -1,4 +1,3 @@
// run-pass
#![feature(specialization)]
//~^ WARN the feature `specialization` is incomplete
@ -8,6 +7,7 @@ trait Iterate<'a> {
}
impl<'a, T> Iterate<'a> for T where T: Check {
default type Ty = ();
//~^ ERROR the trait bound `(): Valid` is not satisfied
default fn iterate(self) {}
}

View File

@ -7,5 +7,15 @@ LL | #![feature(specialization)]
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
warning: 1 warning emitted
error[E0277]: the trait bound `(): Valid` is not satisfied
--> $DIR/issue-38091.rs:8:5
|
LL | trait Iterate<'a> {
| ----------------- required by `Iterate`
...
LL | default type Ty = ();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,24 @@
// Check that we check that default associated types satisfy the required
// bounds on them.
#![feature(specialization)]
//~^ WARNING `specialization` is incomplete
trait X {
type U: Clone;
fn unsafe_clone(&self, x: Option<&Self::U>) {
x.cloned();
}
}
// We cannot normalize `<T as X>::U` to `str` here, because the default could
// be overridden. The error here must therefore be found by a method other than
// normalization.
impl<T> X for T {
default type U = str;
//~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied
}
pub fn main() {
1.unsafe_clone(None);
}

View File

@ -0,0 +1,21 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/deafult-associated-type-bound-1.rs:4:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied
--> $DIR/deafult-associated-type-bound-1.rs:18:5
|
LL | trait X {
| ------- required by `X`
...
LL | default type U = str;
| ^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str`
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,22 @@
// Check that generic predicates are also checked for default associated types.
#![feature(specialization)]
//~^ WARNING `specialization` is incomplete
trait X<T> {
type U: PartialEq<T>;
fn unsafe_compare(x: Option<Self::U>, y: Option<T>) {
match (x, y) {
(Some(a), Some(b)) => a == b,
_ => false,
};
}
}
impl<B: 'static, T> X<B> for T {
default type U = &'static B;
//~^ ERROR can't compare `&'static B` with `B`
}
pub fn main() {
<i32 as X<i32>>::unsafe_compare(None, None);
}

View File

@ -0,0 +1,23 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/deafult-associated-type-bound-2.rs:2:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
error[E0277]: can't compare `&'static B` with `B`
--> $DIR/deafult-associated-type-bound-2.rs:16:5
|
LL | trait X<T> {
| ---------- required by `X`
...
LL | default type U = &'static B;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
|
= help: the trait `std::cmp::PartialEq<B>` is not implemented for `&'static B`
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,27 @@
// Check that default generics associated types are validated.
#![feature(specialization)]
#![feature(generic_associated_types)]
//~^^ WARNING `specialization` is incomplete
//~^^ WARNING the feature `generic_associated_types` is incomplete
trait X {
type U<'a>: PartialEq<&'a Self>;
fn unsafe_compare<'b>(x: Option<Self::U<'b>>, y: Option<&'b Self>) {
match (x, y) {
(Some(a), Some(b)) => a == b,
_ => false,
};
}
}
impl<T: 'static> X for T {
default type U<'a> = &'a T;
//~^ ERROR can't compare `T` with `T`
}
struct NotComparable;
pub fn main() {
<NotComparable as X>::unsafe_compare(None, None);
}

View File

@ -0,0 +1,36 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/deafult-generic-associated-type-bound.rs:3:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/deafult-generic-associated-type-bound.rs:4:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: can't compare `T` with `T`
--> $DIR/deafult-generic-associated-type-bound.rs:19:5
|
LL | trait X {
| ------- required by `X`
...
LL | default type U<'a> = &'a T;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T`
|
= help: the trait `std::cmp::PartialEq` is not implemented for `T`
= note: required because of the requirements on the impl of `for<'a> std::cmp::PartialEq` for `&'a T`
help: consider further restricting this bound
|
LL | impl<T: 'static + std::cmp::PartialEq> X for T {
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 2 warnings emitted
For more information about this error, try `rustc --explain E0277`.