В последнем сообщении упоминалось, как возник код ошибки E0611. В этом посте речь пойдет о частях языка, которые мы не рассматриваем в коде ошибки, таких как черты и замыкания, а также о дальнейших изменениях дизайна в коде ошибки.

Во-первых, мы называем его E0621, так как E0620 - это наивысший код ошибки до сих пор.

Часовой мозговой штурм закончился очень интересными случаями. До сих пор мы рассматривали только бесплатные функции, такие как foo(), и функции в трейтах.

Подробнее о чертах…

trait Foo {
   fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
              - consider changing the type of `x` to &'a i32

Проблема с выдачей ошибки означает, что нам также нужно изменить все соответствующие ей импы. Давайте посмотрим на эти два случая,

impl Foo for () {
   // here, we implement the same signature as the trait declaration
   fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
      if x > y { x } else { y }
   }
}

В приведенном выше случае сигнатура признака может быть виновата, т.е. в ней отсутствует объявление времени жизни. Тело функции тоже может быть виновато, т.е. fn должна возвращать только y. В таких случаях неясно, какая из двух является реальной проблемой, и изменение объявления impl означает также изменение свойства. Следовательно, мы предполагаем, что автор мог забыть добавить 'a к подписи.

trait Bar {
   fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32;
}
impl Bar for () {
   // here, we implement a less strict signature than the trait. 
   // This is allowed in Rust.
   fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
      if x > y { x } else { y }
   }
}

Вызывало беспокойство то, нужно ли рассматривать такие случаи для E0621.. Давайте посмотрим на другой пример.

Impl Items

В случае Impl Items код ошибки касается только Inherent Impls, например

struct Foo {
  field: i32
}
impl Foo {
   fn foo<'a>(&'a self, x: &i32) -> &'a i32 {
       if true { &self.field } else { x }
}

что дает нам

Приведенный ниже фрагмент кода выполняет проверку за нас.

Some(hir_map::NodeImplItem(..)) => {
                                let container_id = self.tcx
                                  .associated_item(anonymous_region_binding_scope)
                                    .container
                                    .id();
                                if      self.tcx.impl_trait_ref(container_id).is_some() {
   // checks whether the ImplItem is implementing a Trait                                
                                    return None;
                                }
                            }

Кроме того, на данный момент не обрабатываются случаи, когда анонимный регион находится в self.

fn foo2<'a>(&self, x: &'a i32) -> &'a i32 {
  if true { &self.field } else { x }
}

Во-первых, для него неправильное форматирование. Во-вторых, у нас может быть случай, подобный приведенному ниже, когда функция self.field не возвращает, и, следовательно, нам не нужно беспокоиться о его времени жизни. Анонимному региону соответствует только возвращаемый тип.

fn foo<'a>(&self, x: &'a i32) -> &i32 {
                                  ---- consider changing to `&'a i32`
   x
}

Случаи, когда анонимная область находится в возвращаемом типе, в настоящее время также не обрабатываются.

В следующем посте будут проверяться элементы Impl и многое другое в анонимных регионах в self и возвращаемом типе. А пока до свидания :). Спасибо за чтение.