Fix issues in name resolution

Looking up a name x in the library scope or in a prefix can also return
the setter name x=. There were several situations that were not handled
right.

- a getter x and a setter x= should not result in a duplicate name
  error (and thus a resolution error at runtime).

- when looking for an untangled name x but a setter x= is found first,
  keep looking for x.

BUG=25625
R=regis@google.com

Review URL: https://codereview.chromium.org/1752203002 .
This commit is contained in:
Matthias Hausner 2016-03-02 10:44:28 -08:00
parent f24c3609f0
commit 5a0a097188
3 changed files with 49 additions and 10 deletions

View file

@ -9403,8 +9403,7 @@ void Library::AddObject(const Object& obj, const String& name) const {
}
// Lookup a name in the library's re-export namespace. The name is
// unmangled, i.e. no getter or setter names should be looked up.
// Lookup a name in the library's re-export namespace.
RawObject* Library::LookupReExport(const String& name) const {
if (HasExports()) {
const Array& exports = Array::Handle(this->exports());
@ -9416,7 +9415,13 @@ RawObject* Library::LookupReExport(const String& name) const {
ns ^= exports.At(i);
obj = ns.Lookup(name);
if (!obj.IsNull()) {
break;
// The Lookup call above may return a setter x= when we are looking
// for the name x. Make sure we only return when a matching name
// is found.
String& obj_name = String::Handle(obj.DictionaryName());
if (Field::IsSetterName(obj_name) == Field::IsSetterName(name)) {
break;
}
}
}
StorePointer(&raw_ptr()->exports_, exports.raw());
@ -9731,6 +9736,14 @@ RawObject* Library::LookupImportedObject(const String& name) const {
// The newly found object is exported from a Dart system
// library. It is hidden by the previously found object.
// We continue to search.
} else if (Field::IsSetterName(found_obj_name) &&
!Field::IsSetterName(name)) {
// We are looking for an unmangled name or a getter, but
// the first object we found is a setter. Replace the first
// object with the one we just found.
first_import_lib_url = import_lib.url();
found_obj = obj.raw();
found_obj_name = found_obj.DictionaryName();
} else {
// We found two different objects with the same name.
// Note that we need to compare the names again because
@ -10341,6 +10354,7 @@ RawObject* LibraryPrefix::LookupObject(const String& name) const {
String& import_lib_url = String::Handle();
String& first_import_lib_url = String::Handle();
Object& found_obj = Object::Handle();
String& found_obj_name = String::Handle();
for (intptr_t i = 0; i < num_imports(); i++) {
import ^= imports.At(i);
obj = import.Lookup(name);
@ -10356,13 +10370,36 @@ RawObject* LibraryPrefix::LookupObject(const String& name) const {
// from the Dart library.
first_import_lib_url = import_lib.url();
found_obj = obj.raw();
found_obj_name = found_obj.DictionaryName();
} else if (import_lib_url.StartsWith(Symbols::DartScheme())) {
// The newly found object is exported from a Dart system
// library. It is hidden by the previously found object.
// We continue to search.
} else if (Field::IsSetterName(found_obj_name) &&
!Field::IsSetterName(name)) {
// We are looking for an unmangled name or a getter, but
// the first object we found is a setter. Replace the first
// object with the one we just found.
first_import_lib_url = import_lib.url();
found_obj = obj.raw();
found_obj_name = found_obj.DictionaryName();
} else {
// We found two different objects with the same name.
return Object::null();
// Note that we need to compare the names again because
// looking up an unmangled name can return a getter or a
// setter. A getter name is the same as the unmangled name,
// but a setter name is different from an unmangled name or a
// getter name.
if (Field::IsGetterName(found_obj_name)) {
found_obj_name = Field::NameFromGetter(found_obj_name);
}
String& second_obj_name = String::Handle(obj.DictionaryName());
if (Field::IsGetterName(second_obj_name)) {
second_obj_name = Field::NameFromGetter(second_obj_name);
}
if (found_obj_name.Equals(second_obj_name)) {
return Object::null();
}
}
}
}

View file

@ -11632,7 +11632,14 @@ AstNode* Parser::ParseClosurization(AstNode* primary) {
// In the pathological case where a library imports itself with
// a prefix, the name mangling does not help in hiding the private
// name, so we explicitly prevent lookup of private names here.
obj = prefix.LookupObject(extractor_name);
if (is_setter_name) {
String& setter_name =
String::Handle(Z, Field::SetterName(extractor_name));
obj = prefix.LookupObject(setter_name);
}
if (obj.IsNull()) {
obj = prefix.LookupObject(extractor_name);
}
}
if (!prefix.is_loaded() && (parsed_function() != NULL)) {
// Remember that this function depends on an import prefix of an

View file

@ -45,11 +45,6 @@ async_star_regression_2238_test: CompileTimeError, RuntimeError # drt only runti
async_star_cancel_while_paused_test: RuntimeError
async_star_await_pauses_test: Skip # Times out. Issue 23996
accessor_conflict_export2_test: RuntimeError # Issue 25625
accessor_conflict_import2_test: RuntimeError # Issue 25625
accessor_conflict_import_prefixed2_test: RuntimeError # Issue 25625
accessor_conflict_import_prefixed_test: RuntimeError # Issue 25625
[ ($compiler == none || $compiler == precompiler || $compiler == dart2app) && ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_product) ]
class_keyword_test/02: MissingCompileTimeError # Issue 13627