Skip to content

Type bounds are ignored in trait and impl function definitions #24011

Closed

Description

@fhahn

It seems that rustc does not check if the type paramater satisfy the declared type bounds in trait and impl function definitions, but only for bare functions. Rustc fails on the following code with the following, rather confusing, error message: type &mut std::collections::hash::set::HashSet<[u8]> does not implement any method in scope named insert

But I think that rustc should fail at an earlier stage, because [u8] does not implement core::marker::Sized.

use std::collections::HashSet;

struct Bar;

impl Bar {
    fn test(bar: &mut HashSet<[u8]>) {
        let x: [u8; 3] = [1, 2, 3];
        bar.insert(x);
    }
}

trait Foo {
    fn test(&self, _: &mut HashSet<[u8]>);
}

The following code is a more general example and does not depend on any library.

trait Cons {
    fn myFn(&self);
}

struct Foo<T: Cons> {
    field: T
}

trait Kaboom {
    fn foo(&self, x: Foo<u8>) {}
   // this does NOT fail, but Foo<u8> is no valid type
}

struct KaboomStruct;

impl KaboomStruct {
    fn bar(&self, x: Foo<u8>) {}
   // this does NOT fail, but Foo<u8> is no valid type
}

fn foo(x: Foo<u8>) {}
// this fails, beacuse u8 does not implement Cons

Activity

  1. fhahn commented on Apr 3, 2015

    @fhahn
    ContributorAuthor

    In this commit, I managed to reuse the existing infrastructure to check the bounds of impl function items. I do not really have an in depth understanding of the well formedness checks, but if this approach is reasonable I am pretty sure it is possible to avoid most of the duplicated code.

    But I could not get this approach to work for trait items, because it relies on blank_fn_ctxt.

  2. pnkfelix commented on Apr 3, 2015

    @pnkfelix
    Contributor

    AFAICT, there is no unsoundness exposed by these examples, since any attempt to create instances of the types one needs to pass (to invoke the functions that are unchecked here) will fail ... right?

    I agree there is a bug here; I just want to double-check the above, in terms of how to triage it.

  3. fhahn commented on Apr 3, 2015

    @fhahn
    ContributorAuthor
  4. pnkfelix commented on Apr 3, 2015

    @pnkfelix
    Contributor
  5. nikomatsakis commented on Apr 4, 2015

    @nikomatsakis
    Contributor

    I've noticed this sort of thing before. I can look into it. Probably worth trying to do before 1.0.

  6. nikomatsakis commented on Apr 4, 2015

    @nikomatsakis
    Contributor

    triage: P-high (1.0)

  7. added this to the 1.0 milestone on Apr 4, 2015
  8. self-assigned this
    on Apr 4, 2015
  9. apasel422 commented on Apr 4, 2015

    @apasel422
    Contributor

    This is related to #19182.

  10. apasel422 commented on Apr 9, 2015

    @apasel422
    Contributor

    A similar issue with default type parameters that compiles successfully:

    trait Bar {}
    struct Foo<T = usize>(T) where T: Bar;

    Foo<usize> cannot be constructed, but it doesn't make sense to allow T to be defaulted to usize. It seems that this could be a backwards compatibility issue, if we ever wanted to forbid this nonsensical declaration in the future. The same goes for default type parameters in other kinds of items.

  11. removed this from the 1.0 milestone on May 21, 2015
  12. arielb1 commented on Aug 14, 2015

    @arielb1
    Contributor

    Fixed by #27641.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions